diff --git a/CHANGELOG.md b/CHANGELOG.md index 77f4e39..e64fcd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to `laravel-form-components` will be documented in this file ### What's Changed -- Add Laravel 10.x support +- Add Laravel 10.x support **Full Changelog**: https://github.com/rawilk/laravel-form-components/compare/v7.1.6...v7.1.7 @@ -14,7 +14,7 @@ All notable changes to `laravel-form-components` will be documented in this file ### Fixed -- Fix css minification issue in custom-select.css +- Fix css minification issue in custom-select.css **Full Changelog**: https://github.com/rawilk/laravel-form-components/compare/v7.1.5...v7.1.6 @@ -22,475 +22,475 @@ All notable changes to `laravel-form-components` will be documented in this file ### Updated -- Update blade heroicon references for v2 +- Update blade heroicon references for v2 ## 7.1.4 - 2022-08-24 ### Updated -- Update blade heroicon references for v2 +- Update blade heroicon references for v2 ## 7.1.3 - 2022-03-30 ### Fixed -- Prevent checkbox/radios from emitting the `input` event in custom selects to prevent it interfering with their toggle handlers on each option +- Prevent checkbox/radios from emitting the `input` event in custom selects to prevent it interfering with their toggle handlers on each option ## 7.1.2 - 2022-03-29 ### Fixed -- Provide better `x-model` support for `switch-toggle` component -- Defer to `\Illuminate\Support\Js::from()` for setting on/off values for `switch-toggle` component +- Provide better `x-model` support for `switch-toggle` component +- Defer to `\Illuminate\Support\Js::from()` for setting on/off values for `switch-toggle` component ## 7.1.1 - 2022-03-25 ### Updated -- Add text alignment dropdown to quill editor toolbar by default +- Add text alignment dropdown to quill editor toolbar by default ## 7.1.0 - 2022-03-25 ### Added -- Add Quill Rich Text Editor component - [#53](https://github.com/rawilk/laravel-form-components/pull/53) +- Add Quill Rich Text Editor component - [#53](https://github.com/rawilk/laravel-form-components/pull/53) ### Updated -- Update vendor cdn versions in config +- Update vendor cdn versions in config ## 7.0.6 - 2022-03-16 ### Fixed -- Prevent JavaScript errors on custom select when calling `.some` on non-arrays +- Prevent JavaScript errors on custom select when calling `.some` on non-arrays ## 7.0.5 - 2022-02-22 ### Fixed -- Handle `null` value updates better when a browser event is emitted to custom select components +- Handle `null` value updates better when a browser event is emitted to custom select components ## 7.0.4 - 2022-02-09 ### Changed -- Wrap each css file in a `@layer components` -- Update required tailwind colors +- Wrap each css file in a `@layer components` +- Update required tailwind colors ### Fixed -- Force custom/tree select null values to get updated when using `wire:model.defer` +- Force custom/tree select null values to get updated when using `wire:model.defer` ## 7.0.3 - 2022-02-08 ### Fixed -- Use correct label on multi custom selects for selected option +- Use correct label on multi custom selects for selected option ## 7.0.2 - 2022-02-08 ### Fixed -- Fix typo in custom select x-data declaration -- Use `langPath()` helper to publish lang files to correct directory +- Fix typo in custom select x-data declaration +- Use `langPath()` helper to publish lang files to correct directory ## 7.0.1 - 2022-02-08 ### Fixed -- Fix keyboard nav on custom select JS errors when no name is provided -- Make timezone select compatible with new version of custom select +- Fix keyboard nav on custom select JS errors when no name is provided +- Make timezone select compatible with new version of custom select ## 7.0.0 - 2022-02-07 ### Added -- Add new `` custom select component -- Add new `` component -- Add new `` component -- Add livewire version of custom select component -- Add livewire version of tree select component -- Add various helper components for custom/tree select components +- Add new `` custom select component +- Add new `` component +- Add new `` component +- Add livewire version of custom select component +- Add livewire version of tree select component +- Add various helper components for custom/tree select components ### Changed -- **Breaking Change:** Bump minimum Laravel version to `8.70` -- **Breaking Change:** Move styles into `resources/css` directory, which will require a different directory and file to import into stylesheets -- **Breaking Change:** Change `textField` prop on `customSelect` to `labelField` -- **Breaking Change:** Change defaults of `valueField` and `labelField` on custom select component to `id` and `name`, respectively -- **Breaking Change:** Rename `min` and `max` props on custom select to `minSelected` and `maxSelected`, respectively -- **Breaking Change:** Require a flat array of options on custom select, even if they contain "opt groups" -- **Breaking Change:** Remove `wire-listeners` from custom select -- Add various new props to custom select component -- Change default styling of custom select component -- Add Laravel 9.* compatibility -- Add PHP 8.1 compatibility -- Update Alpine JS CDN version in config +- **Breaking Change:** Bump minimum Laravel version to `8.70` +- **Breaking Change:** Move styles into `resources/css` directory, which will require a different directory and file to import into stylesheets +- **Breaking Change:** Change `textField` prop on `customSelect` to `labelField` +- **Breaking Change:** Change defaults of `valueField` and `labelField` on custom select component to `id` and `name`, respectively +- **Breaking Change:** Rename `min` and `max` props on custom select to `minSelected` and `maxSelected`, respectively +- **Breaking Change:** Require a flat array of options on custom select, even if they contain "opt groups" +- **Breaking Change:** Remove `wire-listeners` from custom select +- Add various new props to custom select component +- Change default styling of custom select component +- Add Laravel 9.\* compatibility +- Add PHP 8.1 compatibility +- Update Alpine JS CDN version in config ### Fixed -- Various bug fixes in custom select and other components +- Various bug fixes in custom select and other components ## 6.0.2 - 2022-01-10 ### Fixed -- Support for get the old value of a switch toggle without livewire (https://github.com/rawilk/laravel-form-components/pull/41) +- Support for get the old value of a switch toggle without livewire (https://github.com/rawilk/laravel-form-components/pull/41) ## 6.0.1 - 2021-11-11 ### Updated -- Add support for `x-model` on inputs -- Add `onOpen` slot to date picker component +- Add support for `x-model` on inputs +- Add `onOpen` slot to date picker component ## 6.0.0 - 2021-09-20 ### Added -- Register all components under a the `form-components::` namespace +- Register all components under a the `form-components::` namespace ### Fixed -- Fix button display issues when passing values manually to `custom-select` ([#34](https://github.com/rawilk/laravel-form-components/issues/34)) +- Fix button display issues when passing values manually to `custom-select` ([#34](https://github.com/rawilk/laravel-form-components/issues/34)) ### Updated -- Update asset versions in the config -- Reference all `form-components` components using `` instead of `` -- Add better support for multi `custom-select` in non-livewire forms ([#34](https://github.com/rawilk/laravel-form-components/issues/34)) +- Update asset versions in the config +- Reference all `form-components` components using `` instead of `` +- Add better support for multi `custom-select` in non-livewire forms ([#34](https://github.com/rawilk/laravel-form-components/issues/34)) ### Changed -- Switch from rollup to laravel-mix for compiling package JavaScript +- Switch from rollup to laravel-mix for compiling package JavaScript ### Breaking changes -- Increase minimum Laravel version to `8.56` -- Remove ability to override component views in the config (in favor of just publishing the package's views) +- Increase minimum Laravel version to `8.56` +- Remove ability to override component views in the config (in favor of just publishing the package's views) ## 5.1.0 - 2021-07-26 ### Added -- Add custom `after` slot to allow custom markup for "trailing addons" +- Add custom `after` slot to allow custom markup for "trailing addons" ## 5.0.5 - 2021-07-13 ### Fixed -- Update `custom-select` component to use `$nextTick` in `x-init` for Alpine.js v3 [(#25)](https://github.com/rawilk/laravel-form-components/pull/25) +- Update `custom-select` component to use `$nextTick` in `x-init` for Alpine.js v3 [(#25)](https://github.com/rawilk/laravel-form-components/pull/25) ## 5.0.4 - 2021-07-02 ### Fixed -- Fix issues with timezone custom select options -- Update custom select "selected option" styling +- Fix issues with timezone custom select options +- Update custom select "selected option" styling ### Updated -- Use the new `Alpine.data(...)` to define the `customSelect` Alpine component +- Use the new `Alpine.data(...)` to define the `customSelect` Alpine component ## 5.0.3 - 2021-06-25 ### Fixed -- Add backwards compatibility for Laravel 8.0 - 8.26 by adding a `class` macro to `ComponentAttributeBag::class` if the method does not exist +- Add backwards compatibility for Laravel 8.0 - 8.26 by adding a `class` macro to `ComponentAttributeBag::class` if the method does not exist ## 5.0.2 - 2021-06-24 ### Fixed -- Fix syntax error in checkbox/radio component +- Fix syntax error in checkbox/radio component ## 5.0.1 - 2021-06-24 ### Fixed -- Fix syntax issues with FilePond component +- Fix syntax issues with FilePond component ### Updated -- Add `hasStartsWith` macro for blade component attributes +- Add `hasStartsWith` macro for blade component attributes ## 5.0.0 - 2021-06-23 ### Added -- Add Alpine.js v3 support +- Add Alpine.js v3 support ### Removed -- Remove Alpine.js v2 support +- Remove Alpine.js v2 support ### Updated -- Update tailwind version to `2.2.2` in `laravel-form-components-styles` sub-package -- Remove `postcss` in favor of tailwind cli in `laravel-form-components-styles` sub-package -- Update dev dependencies +- Update tailwind version to `2.2.2` in `laravel-form-components-styles` sub-package +- Remove `postcss` in favor of tailwind cli in `laravel-form-components-styles` sub-package +- Update dev dependencies ## 4.0.8 - 2021-06-01 ### Fixed -- Fix issue with date picker not always showing the currently selected date when opened +- Fix issue with date picker not always showing the currently selected date when opened ## 4.0.7 - 2021-04-08 ### Fixed -- Fix leading icon size and z-index issues +- Fix leading icon size and z-index issues ## 4.0.6 - 2021-03-31 ### Fixed -- Fix FilePond background color issue +- Fix FilePond background color issue ## 4.0.5 - 2021-03-31 ### Fixed -- Prevent custom select placeholder being rendered twice +- Prevent custom select placeholder being rendered twice ## 4.0.4 - 2021-03-31 ### Fixed -- Fix next/previous month button styling on flatpickr +- Fix next/previous month button styling on flatpickr ## 4.0.3 - 2021-03-30 ### Fixed -- Fix issue with date-picker toggle icon trying to render for a `false` value -- Fix minor styling issues with flatpickr +- Fix issue with date-picker toggle icon trying to render for a `false` value +- Fix minor styling issues with flatpickr ## 4.0.2 - 2021-03-30 ### Fixed -- Fix issue with inputs that have no leading addons having no border radius +- Fix issue with inputs that have no leading addons having no border radius ## 4.0.1 - 2021-03-30 ### Fixed -- Fix border radius issue with inputs that have leading addons -- Fix width issue for leading addons +- Fix border radius issue with inputs that have leading addons +- Fix width issue for leading addons ## 4.0.0 - 2021-03-29 ### Changed -- Inline most tailwind class names on form components -- Remove majority of styles from stylesheet -- Change styling from sass to css/postcss -- Enable border by default on `` when it is inline and not the first child in a container -- Enable margins on `` by default -- Change how `` "scrolls" to each option -- Switch any icons rendered with `svg()` helper to be rendered with `` blade component instead +- Inline most tailwind class names on form components +- Remove majority of styles from stylesheet +- Change styling from sass to css/postcss +- Enable border by default on `` when it is inline and not the first child in a container +- Enable margins on `` by default +- Change how `` "scrolls" to each option +- Switch any icons rendered with `svg()` helper to be rendered with `` blade component instead ### Added -- Add ability to specify grid columns on `` component (when inline) -- Add `$optional` and `$hint` attributes to `` component +- Add ability to specify grid columns on `` component (when inline) +- Add `$optional` and `$hint` attributes to `` component ### Removed -- Remove `$fixedPosition` prop from `` +- Remove `$fixedPosition` prop from `` ### Fixed -- Fix array to string conversion error on textarea when no value is passed in to it -- Prevent `$wire` from breaking `` when not used in a livewire component -- `` will now position itself correctly and will not require the `fixed-position` prop anymore (requires Popper.js) -- Add missing translations to form-components translation file -- Render timezone-select with correctly when using a component name prefix ([#16](https://github.com/rawilk/laravel-form-components/pull/16)) +- Fix array to string conversion error on textarea when no value is passed in to it +- Prevent `$wire` from breaking `` when not used in a livewire component +- `` will now position itself correctly and will not require the `fixed-position` prop anymore (requires Popper.js) +- Add missing translations to form-components translation file +- Render timezone-select with correctly when using a component name prefix ([#16](https://github.com/rawilk/laravel-form-components/pull/16)) ## 3.1.1 - 2021-03-01 ### Fixed -- Prevent inputs from rendering the string `[]` when name is omitted +- Prevent inputs from rendering the string `[]` when name is omitted ## 3.1.0 - 2021-02-24 ### Added -- Add `extra-attributes` property to inputs to allow more options for attribute forwarding +- Add `extra-attributes` property to inputs to allow more options for attribute forwarding ## 3.0.6 - 2021-02-22 ### Fixed -- Stop using strict comparison for finding a "selected" option in select component ([#11](https://github.com/rawilk/laravel-form-components/issues/11)) +- Stop using strict comparison for finding a "selected" option in select component ([#11](https://github.com/rawilk/laravel-form-components/issues/11)) ## 3.0.5 - 2021-02-03 ### Fixed -- Fix bug with multiple custom select "selectedOption" not updating correctly and throwing JS errors +- Fix bug with multiple custom select "selectedOption" not updating correctly and throwing JS errors ## 3.0.4 - 2021-01-22 ### Updated -- Update flatpickr dependency to version `4.6.9` +- Update flatpickr dependency to version `4.6.9` ## 3.0.3 - 2021-01-08 ### Fixed -- Fix array to string conversion error with `` on value field +- Fix array to string conversion error with `` on value field ## 3.0.2 - 2020-12-21 ### Fixed -- Fix issue with `checked` attribute always being set to `false` on checkbox component +- Fix issue with `checked` attribute always being set to `false` on checkbox component ## 3.0.1 - 2020-12-18 ### Fixed -- Fix issue on `custom-select` where options were always empty +- Fix issue on `custom-select` where options were always empty ## 3.0.0 - 2020-12-18 ### Breaking Changes -- Drop support for php 7 +- Drop support for php 7 ### Added -- Add `container-class` prop to inputs -- Add language file for any text used in components -- Add switch toggle component (``) +- Add `container-class` prop to inputs +- Add language file for any text used in components +- Add switch toggle component (``) ### Changed -- Allow `form-group` component label to be omitted by passing in `false` for `label` -- Update alpine dependency to version `2.8.0` -- Lighten up input placeholder color (apply `placeholder-gray-400` to inputs) +- Allow `form-group` component label to be omitted by passing in `false` for `label` +- Update alpine dependency to version `2.8.0` +- Lighten up input placeholder color (apply `placeholder-gray-400` to inputs) ## 2.0.2 - 2020-11-30 ### Added -- Add class `group` to custom select option elements +- Add class `group` to custom select option elements ### Changed -- Change `x-if` to `x-show` on custom select button display +- Change `x-if` to `x-show` on custom select button display ## 2.0.1 - 2020-11-30 ### Added -- Add `custom-select-value-changed` event emitted on custom select +- Add `custom-select-value-changed` event emitted on custom select ### Fixed -- Fix custom select empty id issue -- Fix custom select filter loading icon styles -- Fix date picker clear button styles -- Fix date picker styles when livewire re-renders it +- Fix custom select empty id issue +- Fix custom select filter loading icon styles +- Fix date picker clear button styles +- Fix date picker styles when livewire re-renders it ## 2.0.0 - 2020-11-27 ### Changed -- Change styling to be compatible with TailwindCSS v2 -- Change color classes to more abstract names like `primary` or `danger` - see the [upgrade guide](https://randallwilk.dev/docs/laravel-form-components/v2/upgrade#styling) for more info -- `` component now renders options in an `x-for` loop and only accepts an array of options now -- `` component now uses `wire:filter` as a livewire method name to perform server-side filtering -- Change how alpine click event is registered on password component (from `@click` to `x-on:click`) -- Make `` compatible with new api for `` -- Change default clear icon for `` +- Change styling to be compatible with TailwindCSS v2 +- Change color classes to more abstract names like `primary` or `danger` - see the [upgrade guide](https://randallwilk.dev/docs/laravel-form-components/v2/upgrade#styling) for more info +- `` component now renders options in an `x-for` loop and only accepts an array of options now +- `` component now uses `wire:filter` as a livewire method name to perform server-side filtering +- Change how alpine click event is registered on password component (from `@click` to `x-on:click`) +- Make `` compatible with new api for `` +- Change default clear icon for `` ### Added -- Add `buttonDisplay` slot to `` component -- Add `optionDisplay` slot to `` component -- Add `wireListeners` property to `` component -- Add `$maxOptions` property to `` component -- Add ability for custom select options to be dependent on other custom selects -- Add php 8 support +- Add `buttonDisplay` slot to `` component +- Add `optionDisplay` slot to `` component +- Add `wireListeners` property to `` component +- Add `$maxOptions` property to `` component +- Add ability for custom select options to be dependent on other custom selects +- Add php 8 support ### Removed -- Remove `` blade component -- Remove `array` type hint on `$options` attribute on `` to allow for more flexibility (i.e. passing in Collections) +- Remove `` blade component +- Remove `array` type hint on `$options` attribute on `` to allow for more flexibility (i.e. passing in Collections) ## 1.4.14 - 2020-11-09 ### Changed -- Change how custom select values are compared +- Change how custom select values are compared ## 1.4.13 - 2020-11-09 ### Changed -- Change how custom select options are selected +- Change how custom select options are selected ## 1.4.12 - 2020-11-08 ### Changed -- Allow timezone custom select to be fixed positioned +- Allow timezone custom select to be fixed positioned ## 1.4.11 - 2020-11-08 ### Changed -- Allow custom select menu to be fixed positioned instead of absolute -- Tweak password input styling +- Allow custom select menu to be fixed positioned instead of absolute +- Tweak password input styling ## 1.4.10 - 2020-11-02 ### Fixed -- Prevent toggle icon from overlapping with icons injected into the password input by password managers such as Lastpass +- Prevent toggle icon from overlapping with icons injected into the password input by password managers such as Lastpass ## 1.4.9 - 2020-10-30 ### Changed -- Change custom select option selection tracking to use session storage +- Change custom select option selection tracking to use session storage ## 1.4.8 - 2020-10-29 ### Fixed -- Adjust how selected options are tracked for custom selects that are multiple selectable and wire filterable -- see [livewire issue #763](https://github.com/livewire/livewire/issues/763) -- Adjust selected display styling for multi custom-select +- Adjust how selected options are tracked for custom selects that are multiple selectable and wire filterable -- see [livewire issue #763](https://github.com/livewire/livewire/issues/763) +- Adjust selected display styling for multi custom-select ## 1.4.7 - 2020-10-28 ### Fixed -- Fix z-index issue on custom select container -- Preserve custom select display if selected option disappears -- Prevent custom select options from being selected and de-selected in the same click -- Allow tab to work normally when pressed and custom select button trigger is focused -- Re-focus custom select trigger button when `esc` key is pressed and menu is opened -- Make custom select clear button always vertically centered +- Fix z-index issue on custom select container +- Preserve custom select display if selected option disappears +- Prevent custom select options from being selected and de-selected in the same click +- Allow tab to work normally when pressed and custom select button trigger is focused +- Re-focus custom select trigger button when `esc` key is pressed and menu is opened +- Make custom select clear button always vertically centered ## 1.4.6 - 2020-10-26 ### Fixed -- Add `wire:ignore` to the `custom-select` button display to prevent livewire from re-rendering it +- Add `wire:ignore` to the `custom-select` button display to prevent livewire from re-rendering it ## 1.4.5 - 2020-10-26 ### Changed -- Update how `custom-select` is initialized +- Update how `custom-select` is initialized ## 1.4.4 - 2020-10-26 @@ -500,89 +500,89 @@ Patch release for 1.4.3 ### Fixed -- [CustomSelect] Prevent trying to find children when $refs.menu is not present -- [CustomSelect] Prevent menu and container from being referenced if not present +- [CustomSelect] Prevent trying to find children when $refs.menu is not present +- [CustomSelect] Prevent menu and container from being referenced if not present ## 1.4.2 - 2020-10-26 ### Changed -- Allow form-group component to accept a `label-id` attribute to allow giving the label an id +- Allow form-group component to accept a `label-id` attribute to allow giving the label an id ## 1.4.1 - 2020-10-26 ### Fixed -- Give custom select menu container a higher z-index to prevent it from appearing under other form inputs +- Give custom select menu container a higher z-index to prevent it from appearing under other form inputs ## 1.4.0 - 2020-10-25 ### Added -- Add new `custom-select` component ([#4](https://github.com/rawilk/laravel-form-components/issues/4)) -- Add new `@fcJavaScript` blade directive for custom package JavaScript +- Add new `custom-select` component ([#4](https://github.com/rawilk/laravel-form-components/issues/4)) +- Add new `@fcJavaScript` blade directive for custom package JavaScript ### Changed -- Modify `@fcScripts` to output package JavaScript that powers custom components -- Change `timezone-select` to support using both native select and new `custom-select` component +- Modify `@fcScripts` to output package JavaScript that powers custom components +- Change `timezone-select` to support using both native select and new `custom-select` component ## 1.3.2 - 2020-10-15 ### Added -- Add `file-pond-clear` event listener to clear out all files in the FilePond instance +- Add `file-pond-clear` event listener to clear out all files in the FilePond instance ## 1.3.1 - 2020-10-15 ### Added -- Add a `wire:model` watcher to the `file-pond` component to watch for manual file deletions +- Add a `wire:model` watcher to the `file-pond` component to watch for manual file deletions ### Changed -- Change how FilePond is initialized on the `file-pond` component. +- Change how FilePond is initialized on the `file-pond` component. ## 1.3.0 - 2020-10-14 ### Added -- Add a file input component ([#2](https://github.com/rawilk/laravel-form-components/issues/2)) -- Add a [FilePond](https://pqina.nl/filepond/) component ([#2](https://github.com/rawilk/laravel-form-components/issues/2)) +- Add a file input component ([#2](https://github.com/rawilk/laravel-form-components/issues/2)) +- Add a [FilePond](https://pqina.nl/filepond/) component ([#2](https://github.com/rawilk/laravel-form-components/issues/2)) ### Changed -- Only render the id attribute on inputs if an id is set on the component +- Only render the id attribute on inputs if an id is set on the component ## 1.2.1 - 2020-10-12 ### Changed -- Only render the checkbox/radio label markup if a label or description is present +- Only render the checkbox/radio label markup if a label or description is present ## 1.2.0 - 2020-10-06 ### Added -- Add a date picker component ([#7](https://github.com/rawilk/laravel-form-components/pull/7)) -- Add directives `@fcStyles` and `@fcScripts` for linking to 3rd party CDN libraries when not in production ([view commit](https://github.com/rawilk/laravel-form-components/commit/5f923ec723c4295128150ee6aaecd4f6797cfafb)) +- Add a date picker component ([#7](https://github.com/rawilk/laravel-form-components/pull/7)) +- Add directives `@fcStyles` and `@fcScripts` for linking to 3rd party CDN libraries when not in production ([view commit](https://github.com/rawilk/laravel-form-components/commit/5f923ec723c4295128150ee6aaecd4f6797cfafb)) ### Changed -- Change format of timezone display in select options +- Change format of timezone display in select options ## 1.1.1 - 2020-09-18 ### Fixed -- Move x-cloak directive in x-password component to the toggle icon so autofocus can work properly on the input. +- Move x-cloak directive in x-password component to the toggle icon so autofocus can work properly on the input. ## 1.1.0 - 2020-09-16 ### Added -- Add timezone select component +- Add timezone select component ## 1.0.0 - 2020-09-13 -- initial release +- initial release diff --git a/README.md b/README.md index 9fda86b..7f9981f 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,24 @@ composer require rawilk/laravel-form-components ``` You can publish the config file with: + ```bash -php artisan fc:publish +php artisan vendor:publish --tag="form-components-config" ``` -**Tip:** You can also publish the package views by adding the `--views` flag to the command: +You can view the default configuration here: https://github.com/rawilk/laravel-form-components/blob/main/config/form-components.php + +You can publish the package's views with this command: ```bash -php artisan fc:publish --views +php artisan vendor:publish --tag="form-components-views" ``` -You can view the default configuration here: https://github.com/rawilk/laravel-form-components/blob/main/config/form-components.php +If you want to override the package's language lines, you can publish them with this command: + +```bash +php artisan vendor:publish --tag="form-components-translations" +``` ## Documentation @@ -41,7 +48,7 @@ For a demo of some of the components, please visit: https://laravel-form-compone ## Testing -``` bash +```bash composer test ``` @@ -59,22 +66,23 @@ Please review [my security policy](../../security) on how to report security vul ## Credits -- [Randall Wilk](https://github.com/rawilk) -- [All Contributors](../../contributors) +- [Randall Wilk](https://github.com/rawilk) +- [All Contributors](../../contributors) This package is also heavily inspired by [Laravel Form Components](https://github.com/protonemedia/laravel-form-components) and [Blade UI Kit](https://blade-ui-kit.com/). +A lot of inspiration for some JS components is taken from [Alpine Headless Components](https://alpinejs.dev/components#headless). ## Alternatives This package was created to satisfy my own needs and preferences, and relies on TailwindCSS, TailwindUI, and AlpineJS for styling and functionality. You can always try one of these alternatives if your needs differ: -- [Blade UI Kit](https://blade-ui-kit.com/) -- [Laravel Form Components](https://github.com/protonemedia/laravel-form-components) +- [Blade UI Kit](https://blade-ui-kit.com/) +- [Laravel Form Components](https://github.com/protonemedia/laravel-form-components) ## Disclaimer -This package is not affiliated with, maintained, authorized, endorsed or sponsored by Laravel, TailwindCSS, Laravel Livewire, or any of its affiliates. +This package is not affiliated with, maintained, authorized, endorsed or sponsored by Laravel, TailwindCSS, Laravel Livewire, Alpine.js, or any of its affiliates. ## License diff --git a/config/form-components.php b/config/form-components.php index d6df63a..cb913e7 100644 --- a/config/form-components.php +++ b/config/form-components.php @@ -109,7 +109,7 @@ // Defaults for the date picker component. 'date_picker' => [ // Allow date picker to open from clicking on the input by default. - 'click_opens' => true, + 'click_opens' => false, // Allow user to modify the text of the input by default. 'allow_input' => true, diff --git a/docs/_index.md b/docs/_index.md index 2c6eb78..f8a8994 100644 --- a/docs/_index.md +++ b/docs/_index.md @@ -1,5 +1,5 @@ --- -title: v7 +title: v8 slogan: A set of Blade components for TailwindCSS forms. githubUrl: https://github.com/rawilk/laravel-form-components branch: main diff --git a/docs/advanced-usage/addons.md b/docs/advanced-usage/addons.md new file mode 100644 index 0000000..5a4b7cf --- /dev/null +++ b/docs/advanced-usage/addons.md @@ -0,0 +1,208 @@ +--- +title: Addons +sort: 1 +--- + +## Introduction + +Addons provide a way to prepend or append text or an icon to an input. Both leading and trailing addons can be added to the input either by use of props or slots. +When rendering the input, only one type of leading and one type of trailing addon will be rendered at a time. + +In the examples shown on this page, we will be using the `input` component, however addons will work with most other components as well. + +## Leading Addons + +There are three types of "leading" addons offered by this package: leading addon, inline addon, and leading icon. Each of these will be rendered somewhere +on the left side of an input element. + +### Leading Addon + +A leading addon will be rendered as text on top of a light gray background at the beginning of the input. To render a leading +addon, specify the text either in the `leading-addon` attribute or the `leadingAddon` slot. + +Via prop: + +```html + +``` + +Via slot: + +```html + + https:// + +``` + +### Inline Addon + +Inline addon is similar to leading addon, however there is no background behind the text. You are also responsible +for setting the left padding of the input to allow for enough room for your text to fit at the beginning of the +input. + +You can set the inline addon by using the `inline-addon` attribute or the `inlineAddon` slot. + +Via prop: + +```html + +``` + +Via slot: + +```html + + https:// + +``` + +To modify the padding, you should use a custom class on the input. Since this padding value is controlled via a [variable](/docs/laravel-form-components/{version}/advanced-usage/customizing-css#user-content-variables), +you could just use an [arbitrary value](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values) in a custom class name: + +```html + +``` + +This is the equivalent of `pl-4` on the input. However, it's recommended to override the variable value instead. If you do it this way, you need to be sure to make the rule +`!important` (prefix the class name with `!`) so it actually overrides the variable value. + +### Leading Icon + +Instead of text, you can prepend an icon to the input instead. The package is styled for +[blade heroicon svgs](https://github.com/blade-ui-kit/blade-heroicons), but you are free +to use whatever icons you want to. + +To prepend an icon, you can use the `leading-icon` prop, or the `leadingIcon` slot: + +Via prop: + +```html + +``` + +Via slot: + +```html + + + + + +``` + +If you pass the icon name via prop, the component will use the `` component behind-the-scenes to render the component for convenience. + +## Trailing Addons + +There are three types of "trailing" addons offered by this package: trailing addon, trailing inline addon, and trailing icon. These all behave like the leading addon version of them, except now they +will be on the right side of the input element. + +### Trailing Addon + +Like the leading addon, the trailing addon will render text inside a light gray background at the end of the input this time. To render a trailing addon, +specify text in either the `trailing-addon` prop or the `trailingAddon` slot. + +Via prop: + +```html + +``` + +Via slot: + +```html + + lbs + +``` + +### Trailing Inline Addon + +Like the inline addon, the trailing inline addon will add text directly inside the input, but this time on the right +side of the input. Also like the inline addon, you may need to specify a custom padding amount for the input. + +You can add a trailing inline addon by using either the `trailing-inline-addon` attribute or the `trailingInlineAddon` slot. + +Via prop: + +```html + +``` + +Via slot: + +```html + + USD + +``` + +To adjust the amount of padding on the right side on the input, you should override the `--inline-addon-pr` CSS variable. See [Inline Addon](#user-content-inline-addon) +for an example on how to this. + +### Trailing Icon + +You can append an icon to an input similar to prepending one. You can do so using either the `trailing-icon` prop or the `trailingIcon` slot: + +Via prop: + +```html + +``` + +Via slot: + +```html + + + + + +``` + +If you pass the icon name via prop, the component will use the `` component behind-the-scenes to render the component for convenience. + +## Before Slot + +The `before` slot allows you the flexibility to render any kind of HTML you need to directly before the input element. If you have a leading addon on the input, it will render before that markup. + +```html + + +
Before slot content
+
+
+``` + +## After Slot + +The `after` slot allows you the flexibility to render any kind of HTML you need to directly after the input element. If you have a trailing addon on the input, it will render after that markup. + +```html + + +
After slot content
+
+
+``` + +## Addon Slot Attributes + +All types of leading and trailing addons (except the before and after slots) are able to render custom HTML attributes onto the addon markup for you. The only +requirement is that you use the named slot for the addon, and not the prop. + +The following example will add an id and an attribute called data-foo onto the leading addon markup for the input. + +```html + + + Hello world + + +``` + +Those attributes will be rendered onto the `` that wraps `Hello world` and **not** onto the input itself. diff --git a/docs/advanced-usage/customizing-css.md b/docs/advanced-usage/customizing-css.md index a8e0b3f..831792f 100644 --- a/docs/advanced-usage/customizing-css.md +++ b/docs/advanced-usage/customizing-css.md @@ -1,11 +1,12 @@ --- title: Customizing CSS -sort: 1 +sort: 2 --- If you want to change the look of the Laravel Form Components to match the style of your own app, you have multiple options. ## Option 1: Use Your Own Tailwind CSS Configuration + You can import the `index.css` and run every `@apply` rule through your own `tailwind.config.js`. ```css @@ -15,51 +16,53 @@ You can import the `index.css` and run every `@apply` rule through your own `tai @tailwind components; @tailwind utilities; -@import '../../vendor/rawilk/laravel-form-components/resources/css/index.css'; +@import "../../vendor/rawilk/laravel-form-components/resources/css/index.css"; /* override our styles here */ ``` -> {note} If you choose this option, make sure you have the [required variants](#required-variants) included in your `tailwind.config.js` configuration. +> {note} If you choose this option, make sure you have the [required variants](#user-content-required-variants) included in your `tailwind.config.js` configuration. You may also import only the stylesheets you need instead of everything in the index.css file. Most components have their own stylesheets (i.e. `input.css` for input elements). ## Option 2: Copy the CSS To Your Own Project + If you want full-control, you can always copy the each of the stylesheets from `resources/css` to your own project and go wild. In this example, we renamed the file to `custom/laravel-form-components.css`. Beware: you will have to manually keep this CSS in sync with changes in future package updates: ```css /* app.css */ -... - -@import 'custom/laravel-form-components.css'; +... @import "custom/laravel-form-components.css"; ``` -Let's say you wanted to change the background color of disabled inputs. You could do so like this in the file you just created with the pasted in styles from the package: +Let's say you wanted to change the spacing in stacked checkbox groups. You could do so like this in the file you just created with the pasted in styles from the package: ```css /* custom/laravel-form-components.css */ -input[disabled], -textarea[disabled], -select[disabled] { - @apply bg-gray-100; - - /* default styles from the package */ - /*@apply bg-slate-50 cursor-not-allowed;*/ +.form-checkbox-group--stacked { + @apply space-y-2; + + /* styles from the package */ + /*@apply space-y-4;*/ } ... ``` -## Required Variants -If you choose [Option 1](#option-1-use-your-own-tailwind-css-configuration), you will need the following color variants added inside your `tailwind.config.js` file: +## Tailwind Configuration + +Some custom configuration is necessary to ensure our package's CSS compiles correctly, and that the components are styled correctly. + +### Required Variants + +If you choose [Option 1](#user-content-option-1-use-your-own-tailwind-css-configuration), you will need the following color variants added inside your `tailwind.config.js` file: ```js // tailwind.config.js -const colors = require('tailwindcss/colors'); +const colors = require("tailwindcss/colors"); module.exports = { // ... @@ -73,23 +76,30 @@ module.exports = { }; ``` -This will extend the default tailwind color palette to include the `slate` color variant. +This will extend the default tailwind color palette to include the `slate` color variant. There are a few other colors you'll want to make sure you have in your color palette, +such as `blue` and `red`, so if you're using a custom color palette, make sure those colors are included in it. For a comprehensive overview of what colors and utility classes +you'll need in your Tailwind configuration for the package's styles to compile, you can refer to the [variables.css](https://github.com/rawilk/laravel-form-components/blob/{branch}/resources/css/variables.css) file. -> {note} If you have a custom color palette configured, you will need to make sure you have the `blue` and `red` colors configured as well, with all -> levels available (`50` through `900`). +### Plugins -Certain components make use of a custom utility class called `outline-slate`, which adds a 2px dotted outline around the element when focused. If you opt to not add this outline variant to your configuration, it will not affect building the CSS since the package's stylesheet does not reference it; the outline variant is only rendered directly onto the elements it's used for. If you want the outline to show up, you can add the following to a stylesheet in a `@layer utilities`: +The `@tailwindcss/forms` plugin is necessary to for some base styles to be applied to the form components. If you are using the +[switch-toggle](/docs/laravel-form-components/{version}/inputs/switch-toggle) component, you will want to include our custom `switch-toggle` plugin if you plan on rendering it with custom colors. -```css -@layer utilities { - .outline-slate { - outline: 2px dotted theme('colors.slate.400'); - outline-offset: 2px; - } -} +```js +// tailwind.config.js + +module.exports = { + // ... + plugins: [ + require("@tailwindcss/forms"), + + // Only necessary if you're going to use the switch-toggle component with different colors + require("./vendor/rawilk/laravel-form-components/resources/js/tailwind-plugins/switch-toggle"), + ], +}; ``` -## Purge CSS/Tailwind JIT +### Purge CSS/Tailwind JIT Purge CSS is useful for trimming out unused styles from your stylesheets to reduce your overall build size. To ensure the class styles from this package don't get purged from your production build, you should add the following to your @@ -100,29 +110,70 @@ purge css content configuration: ```js module.exports = { // ... - purge: { - content: [ - // Typical laravel app purge css content - './app/**/*.php', - './resources/**/*.php', - './resources/**/*.js', - - // Make sure you add these lines - './vendor/rawilk/laravel-form-components/src/**/*.php', - './vendor/rawilk/laravel-form-components/resources/**/*.php', - './vendor/rawilk/laravel-form-components/resources/js/*.js', - ], - }, + content: [ + // Typical laravel app purge css content + "./app/**/*.php", + "./resources/**/*.php", + "./resources/**/*.js", + + // Make sure you add these lines + "./vendor/rawilk/laravel-form-components/src/**/*.php", + "./vendor/rawilk/laravel-form-components/resources/**/*.php", + "./vendor/rawilk/laravel-form-components/resources/js/*.js", + ], }; ``` -This configuration should also work when using the JIT compiler from Tailwind. +Due to the dynamic nature of how some classes are rendered onto the markup, you may still find some of them being purged by Tailwind. Here's a few you may want to +add to your `safelist` to prevent from being purged: -If some styles are still being purged, it may be useful to wrap the import statement of the package's stylesheet -in a `/* purgecss start ignore */`: +```js +module.exports = { + // ... + safelist: [ + { + pattern: /file-upload__input--*/, + }, + { + pattern: /switch-toggle--*/, + }, + { + pattern: /custom-select__button--*/, + }, + { + // For sizing, e.g. form-input--sm + pattern: /form-input--*/, + }, + { + // For checkbox/radio sizing + pattern: /form-choice--*/, + }, + ], +}; +``` + +You can of course be more selective in what you safelist. For example, instead of using a pattern for the `.form-input--` sizing classes, you could just explicitly add +`form-input--lg` to the safelist array instead of using a regex pattern. + +## Variables + +Some styling for components, such as text color and border colors, can be overridden with CSS variables. For example, if you wanted to override the border color for inputs, +you could add the following to your app's CSS file: ```css -/* purgecss start ignore */ -@import '../../vendor/rawilk/laravel-form-components/resources/css/index.css'; -/* purgecss end ignore */ +... :root { + --input-border-color: theme("colors.green.300"); + --input-dark-border-color: theme("colors.green.500"); +} ``` + +> {note} Make sure to override any variables **after** you've imported the package's CSS. + +For a full reference of the variables you can set in your CSS, please refer to the [variables.css](https://github.com/rawilk/laravel-form-components/blob/{branch}/resources/css/variables.css) file. + +## Dark Mode + +The package's components have also been styled for dark mode and will work with both the class based and OS based strategies. If you are using the class based dark mode +strategy, be sure to use the default `dark` class for dark mode. + +For more information, please refer to [Tailwind's Dark Mode Documentation](https://tailwindcss.com/docs/dark-mode). diff --git a/docs/advanced-usage/extra-attributes.md b/docs/advanced-usage/extra-attributes.md new file mode 100644 index 0000000..32b035c --- /dev/null +++ b/docs/advanced-usage/extra-attributes.md @@ -0,0 +1,33 @@ +--- +title: Extra Attributes +sort: 5 +--- + +## Introduction + +There may be times when you are rendering an input component where you may have an unknown amount of attributes you need to pass to the component. +The most common use case I have for it is when I'm building up an array of attributes for a component, and some attributes are conditional on what I send +to the component. + +The current blade syntax doesn't allow for using conditional logic like `@if` when you're rendering a blade component, so I've come up with a prop called `extraAttributes` +on most of the components offered by this package. This will allow you to pass an array of attributes to the element, and the element will then render them onto the +applicable element for you. + +## Basic Usage + +Here's an arbitrary example of how one could build up an array of attributes in a Livewire component, and then pass them to an input component. + +```php +public function getInputAttributesProperty(): array +{ + return array_filter([ + '@click' => "console.log('hi')", + 'data-name' => $this->name, + 'data-foo' => $this->name === 'foo' ? 'true' : null, + ]); +} +``` + +```html + +``` diff --git a/docs/advanced-usage/overriding-classes.md b/docs/advanced-usage/overriding-classes.md index 93ae1f4..1b2485e 100644 --- a/docs/advanced-usage/overriding-classes.md +++ b/docs/advanced-usage/overriding-classes.md @@ -1,6 +1,6 @@ --- title: Overriding Classes -sort: 3 +sort: 4 --- ## Overriding Classes @@ -9,6 +9,7 @@ When you override a component class with your own, you will need to update the c For the `select` component, it would look like this: **Custom Class:** + ```php app->bind(Label::class, MyCustomLabelClass::class); } diff --git a/docs/advanced-usage/phpstorm-interaction.md b/docs/advanced-usage/phpstorm-interaction.md index 14e324d..f79b651 100644 --- a/docs/advanced-usage/phpstorm-interaction.md +++ b/docs/advanced-usage/phpstorm-interaction.md @@ -1,6 +1,6 @@ --- title: PhpStorm Interaction -sort: 2 +sort: 3 --- ## Extending PhpStorm @@ -11,20 +11,8 @@ You may wish to extend PhpStorm to extend the blade directives of this package: 2. Uncheck "Use default settings", then click on the **Directives** tab. 3. Add the following new directives for the laravel-form-components package: -### @fcStyles - -- has parameter = YES -- Prefix: `` - ### @fcScripts -- has parameter = YES -- Prefix: `` - -### @fcJavaScript - -- has parameter = YES -- Prefix: `` +- has parameter = YES +- Prefix: `` diff --git a/docs/changelog.md b/docs/changelog.md index a0e65e1..e5cc495 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -3,4 +3,4 @@ title: Changelog sort: 6 --- -All notable changes for laravel-form-components are documented [on Github](https://github.com/rawilk/laravel-form-components/blob/master/CHANGELOG.md). +All notable changes for laravel-form-components are documented [on GitHub](https://github.com/rawilk/laravel-form-components/blob/main/CHANGELOG.md). diff --git a/docs/files/file-upload.md b/docs/files/file-upload.md index 5a67e59..7682a15 100644 --- a/docs/files/file-upload.md +++ b/docs/files/file-upload.md @@ -10,10 +10,11 @@ as well just by adding a `wire:model` to the input. ## Installation -Even though the `file-upload` component will work out-of-the-box if you're using the script blade directives in your layout (`@fcScripts`), -we recommend that you install and compile the JavaScript libraries before you deploy to production. +To take advantage of the upload progress offered by the `file-upload` component, the following third-party libraries are required: -- [Alpine.js](https://github.com/alpinejs/alpine) `^2.8` +- Alpine.js + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. ## Basic Usage @@ -23,10 +24,6 @@ In its most basic usage, you can use it as a self-closing component and pass it ``` -> {note} Since the component applies a class of `sr-only` (hides the input) to the input itself, the input must have an id assigned to it -for the label to be able to trigger a click on the input. By default, the component assigns the `id` to the `name` attribute if you don't -provide an `id` to it. - ## Upload Progress By default, if you add a `wire:model` to the component, it will hook into livewire's file uploads and display upload progress when @@ -41,28 +38,33 @@ for the `display-upload-progress` attribute. > {note} Since the upload progress hooks into livewire events, it will not be shown unless you provide a `wire:model` to it. -## Custom Button Label +### Native Progress Bar -By default, the text on the button that is shown says `Select File`. You may optionally specify your own label via an attribute: +By default, the `file-upload` component is configured to render the upload progress in a non-native progress element with aria attributes +for accessibility. This is done to help ensure styling consistency across browsers. If this is not a concern for your application, you can +set the `useNativeProgressBar` attribute to `true`, and the component will use the `` element instead to show upload progress. ```html - + ``` ## Default Slot -The `file-upload` component is based on the photo input example from TailwindUI. This displays a photo to the left of the button. -This slot is completely optional, and can be omitted if you don't need to show a file preview. +The `file-upload` component allows you to place some markup before the input element for something like a photo preview once +a file is selected. The following example shows displaying a user avatar preview in a livewire component: -If you are using livewire and would like to show a photo here, you can do so by following this example: +This slot is completely optional, and can be omitted if you don't need to show a file preview. ```html
@if ($avatar) - - - + + + @endif
@@ -70,18 +72,108 @@ If you are using livewire and would like to show a photo here, you can do so by ## After Slot -You can of course omit the default slot and provide content in the `after` slot to show a file preview on the right side of the button. +You can of course omit the default slot and provide content in the `after` slot to show a file preview on the right side of the input. Other content could also be shown in this slot as well. ```html - -
After slot content.
-
+ +
After input slot content.
+
``` +> {note} You will not have access to the `x-data` scope in the component. Use the [After Input Slot](#user-content-after-input-slot) if you need +> access to it. + +## After Input Slot + +This slot allows for placing any kind of markup after the input and/or file upload progress bar. You will have access to the Alpine variables +`isUploading` and `progress` in this slot. This slot is useful if you are not using Livewire to upload your files, but still want to display +a file upload progress bar. + +> {note} You may need to manually include the `form-components::components.files.partials.upload-progress` view partial if you're not using Livewire. + ## Multiple Files You can use the component to upload multiple files by providing the `multiple` attribute to the component. If you're using livewire and `wire:model`, just make -sure you're model is an array to handle the uploads. +sure your model is an array to handle the uploads. + +## File Type + +For convenience, you may specify a `type` attribute that will limit the types of files that can be selected. If a supported type is entered, the component +will set the `accept` attribute on the file input. The following types are supported: + +| type | rendered accept value | +| ----------- | ----------------------------------------------------------------------------------------------- | +| audio | audio/\* | +| image | image/\* | +| video | video/\* | +| pdf | .pdf | +| csv | .csv | +| spreadsheet | .csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | +| excel | .csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | +| text | text/plain | +| html | text/html | + +If the type you need isn't listed here, or you need to limit the type further, you are free to specify a value for the `accept` attribute yourself. + +## API Reference + +### props + +| prop | description | +| ----------------------- | ------------------------------------------------------------------------------------------- | --- | +| `name` | The name of the file input | +| `id` | The ID of the file input. Defaults to `name` | +| `multiple` | A boolean indicating the file input supports multi-file upload | +| `type` | The type of file the input accepts | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `displayUploadProgress` | A boolean value indicating if the progress bar should be displayed on livewire file uploads | +| `size` | Define a size for the input. Default size is `md` | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `useNativeProgressBar` | A boolean value indicating if a native progress bar should be used. Default is `false` | + | +| `extraAttributes` | Pass an array of HTML attributes to render on the input | + +### slots + +| slot | description | +| ------------ | --------------------------------------------------------------------- | +| `after` | Place to put markup for a file preview on the right side of the input | +| `afterInput` | Allows custom markup inside of the `x-data` scope | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the file upload element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + ], + + 'file_upload' => [ + // Display a file upload progress bar by default. + // Only shows if a "wire:model" is present. + 'display_upload_progress' => true, + + // Use the native HTML5 progress bar by default. + // Not recommended if you need consistent styling across browsers. + 'use_native_progress_bar' => false, + + // Globally apply a CSS class to each file upload container. + 'container_class' => null, + + // Globally apply a CSS class to each file upload input. + 'input_class' => null, + ], +], +``` diff --git a/docs/files/filepond.md b/docs/files/filepond.md index 63b1e5f..9643560 100644 --- a/docs/files/filepond.md +++ b/docs/files/filepond.md @@ -10,11 +10,10 @@ Before using this component, we recommend familiarizing yourself with the FilePo ## Installation -While the `file-pond` component works out-of-the-box when you've [set the directive](/docs/laravel-form-components/{version}/installation#directives), -we recommend that you install and compile the JavaScript libraries before you deploy to production: +The following third-party libraries are required for the `file-pond` component to work properly. -- [Alpine.js](https://github.com/alpinejs/alpine) `^2.8` -- [FilePond](https://pqina.nl/filepond/) `^4.21` +- Alpine.js +- FilePond As per the [FilePond docs](https://pqina.nl/filepond/docs/patterns/installation/), you can install FilePond via npm: @@ -25,15 +24,19 @@ npm i filepond --save You can then import it in your project using imports: ```js -import * as FilePond from 'filepond'; +import * as FilePond from "filepond"; + +window.FilePond = FilePond; ``` -There are also some styles required for FilePond. If you're using Sass, you can import it **before** you import the styles for this package: +There are also some styles required for FilePond. You should import the styles **before** you import the styles for this package: ```css -@import '~filepond/dist/filepond.min.css'; +@import "filepond/dist/filepond.min.css"; ``` +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage The most basic usage of the `file-pond` component involves just adding a self-closing tag: @@ -45,18 +48,15 @@ The most basic usage of the `file-pond` component involves just adding a self-cl This will output the following HTML (omitting JS): ```html -
- +
+
+ +
``` +> {note} The FilePond library will completely remove the input element we are rendering from the component once initialized. + ## Livewire Integration The `file-pond` component integrates smoothly with livewire out-of-the-box and just requires you to @@ -77,6 +77,10 @@ root element generated by FilePond: ``` +In the defaults configuration for the `file-pond` component, you may specify some default options to always set on a +FilePond instance. They will not apply however if you pass in an array of options via the `options` attribute +on the component. + For a full reference of all options, please consult [the FilePond documentation](https://pqina.nl/filepond/docs/patterns/api/filepond-instance/#properties). ### Multiple @@ -89,6 +93,8 @@ to conveniently set the `allowMultiple` option for FilePond. You can limit the number of files accepted when `allowMultiple` is set to `true` by providing `max-files` with an integer value. +This option can be set globally in the config, and on a per-element basis. + ### Disabled You can easily disable the FilePond input by passing `disabled` in as a boolean value. @@ -98,43 +104,48 @@ You can easily disable the FilePond input by passing `disabled` in as a boolean The `allow-drop` boolean attribute has been added as a way to conveniently set the `allowDrop` option. Setting it to `false` will prevent users from being able to drop files onto the input. +This option can be set globally in the config, and on a per-element basis. + ## Callbacks -Since the `options` attribute only accepts scalar values, the component offers an `optionsSlot` slot that will allow you to -specify an option callbacks, such as `server` that you need to: +Since the `options` attribute only accepts scalar values, the component offers a `config` slot that will allow you to +specify an option callbacks, such as `onaddfile`, that you need to: ```html - - server: { - process: () => { ... } - } - + onaddfile(error, file) { // do stuff }, ``` +This slot is inside a function that returns an object. You'll have access to the following variables: + +| variable | description | +| ------------- | -------------------------------------------------------------------------------------------------------------- | +| `instance` | The x-data instance for `filepond`. If you need the filepond instance, you can access it via `instance.__pond` | +| `options` | The options object generated for FilePond by the component | +| `pondOptions` | The options for FilePond our JavaScript generated before calling the config slot | + ## Plugins The `file-pond` component doesn't make use of any FilePond plugins itself, but you can easily install and implement your own plugins. First, install the necessary JavaScript and CSS required by the plugin. A list of plugins [can be found here](https://pqina.nl/filepond/plugins.html). -With the plugin's assets installed, you can make use of the `plugins` slot to initialize the plugin. The following example shows setting up the image -preview FilePond Plugin. +With the plugin's assets installed, you can register them with FilePond either in an external script, or inline in the DOM somewhere. Here's an example +of loading the file type validation plugin in an inline script: ```html - - - FilePond.registerPlugin(FilePondPluginImagePreview); - - + ``` If you're into using CDNs, you can add these lines to your layout file for the above example: ```html - - + ``` ## Manually Deleting Files @@ -144,8 +155,6 @@ find that the files still appear to be in FilePond, even though Livewire has act the `file-pond` component adds a watcher on your `wire:model` by using `@entangle`. Now, when you remove the files manually, the component will pick up on those changes and remove the removed files from the FilePond instance. -You can opt out of this behavior by setting the boolean attribute `watch-value` to `false` on the component. - ## Clear Event Listener You may encounter some edge cases where you may need to clear the files out of the FilePond instance @@ -153,9 +162,95 @@ yourself. When using livewire, this can easily be accomplished by adding the fol component somewhere: ```php -$this->dispatchBrowserEvent('file-pond-clear', ['id' => $this->id]); +$this->emitSelf('file-pond-clear'); +``` + +If you have multiple filepond instances in a Livewire component, you may pass the id of the filepond instance as an argument +to only clear that specific filepond instance. The `id` should be the `id` you give to the filepond instance, which defaults to +the `name` attribute if omitted. + +```php +$this->emitSelf('file-pond-clear', 'avatar'); +``` + +This example will only clear the files out of a filepond instance with the id of `avatar`. + +### Browser Clear Event + +You can also dispatch an event via JavaScript to clear out a filepond instance as well. If you have multiple filepond +components rendered on the page, you may pass in the id of the component as an argument. + +```html + ``` -Each Livewire component has its own unique id assigned to it, so by passing `$this->id` into the -event you're emitting, the component will be able to match the ids and clear the files for the correct -component. +## Type + +For convenience, you may specify a `type` attribute that will limit the types of files that can be selected. If a supported type is entered, the component +will set the `acceptedFileTypes` FilePond option for you. + +| type | rendered accept value | +| ----------- | ----------------------------------------------------------------------------------------------- | +| audio | audio/\* | +| image | image/\* | +| video | video/\* | +| pdf | .pdf | +| csv | .csv | +| spreadsheet | .csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | +| excel | .csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | +| text | text/plain | +| html | text/html | + +> {note} For this to work, you must have the [File Type Validation](https://pqina.nl/filepond/docs/api/plugins/file-validate-type/) plugin installed. +> See [Plugins](#user-content-plugins) for more information. + +## API Reference + +### props + +| prop | description | +| ----------------- | --------------------------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to `name`. | +| `multiple` | A boolean value indicating that multiple files can be uploaded. Defaults to `false` | +| `disabled` | A boolean value indicating the input is disabled | +| `maxFiles` | The maximum amount of files allowed to be uploaded. Only applies if `multiple` is set to `true` | +| `options` | An optional array of FilePond options to set | +| `description` | Set a description inside the filepond markup | +| `type` | Set a type of files that are only allowed to be uploaded. Requires the File Validate plugin from FilePond | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the input | + +### slots + +| slot | description | +| -------- | ----------------------------------------------------------------------------------------------------------- | +| `config` | Provides a place for a JavaScript configuration object for FilePond. Most useful for defining JS callbacks. | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the filepond element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'file_pond' => [ + // Allow drag and drop file uploads by default. + 'allow_drop' => true, + + // Limit multiple file uploads to a certain number of files by default. + // Set to null to allow unlimited files. + 'max_files' => null, + + // Configure FilePond options by default. + 'options' => [], + ], +], +``` diff --git a/docs/form/form-error.md b/docs/form/form-error.md index 8e39f5f..2dbf988 100644 --- a/docs/form/form-error.md +++ b/docs/form/form-error.md @@ -63,7 +63,7 @@ Now we'll use the component's slot and its `messages()` method to render an unor ```html @foreach ($component->messages($errors) as $error) -
  • {{ $error }}
  • +
  • {{ $error }}
  • @endforeach
    ``` @@ -82,3 +82,41 @@ This will output: As you can see we need to pass in the `$errors` message bag to the `messages()` method of the component to grab all the messages for our field. Then we loop over them and render them. + +## API Reference + +### props + +| prop | description | +| --------- | ------------------------------------------------------------------------------------------------------------------------ | +| `name` | The name of the input to render errors for | +| `inputId` | The ID of the input element to render errors for. This is useful for using `aria-describedby` attributes on the element. | +| `bag` | The name of the validation error bag. Defaults to `default` | +| `tag` | The tag name of the element to wrap the error(s) in. Defaults to `

    ` | + +### methods + +The following methods can be accessed in the default slot of the component: + +#### messages + +Access the errors in the error bag based on the name provided to the component. This method requires you to pass the `$errors` +object from the blade template. + +```php +public function messages(\Illuminate\Support\ViewErrorBag $errors): array +``` + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the form-error component. + +```php +'defaults' => [ + 'form_error' => [ + // Define which HTML tag to use for the error message by default. + 'tag' => 'p', + ], +], +``` diff --git a/docs/form/form-group.md b/docs/form/form-group.md index eb4acb5..2493b9b 100644 --- a/docs/form/form-group.md +++ b/docs/form/form-group.md @@ -8,6 +8,14 @@ sort: 4 The form group component can be used to encapsulate an input in order to render a label and error messages automatically and consistently for you. +## Installation + +To take full advantage of the `form-group` component, the following third-party libraries are required: + +- Alpine.js + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage At its most basic usage, you can render the input group with a label and your markup inside it: @@ -45,7 +53,9 @@ with the id given to the error message element. You can disable the showing of error messages in the form group by setting the `show-errors` attribute to `false`: ```html -... + + ... + ``` ## Help Text @@ -53,18 +63,24 @@ You can disable the showing of error messages in the form group by setting the ` You can show form help text by either using the `help-text` attribute or the `helpText` slot: Via prop: + ```html - + Input element ``` Via slot: + ```html Input element - Some helpful text... + Some helpful text... ``` @@ -75,13 +91,15 @@ or left-aligned below in input when the form-group is set to `inline`. We like t optional. ```html -... + + ... + ``` You can also have the component render the text `Optional` automatically for you by passing in `true` for the `optional` attribute. ```html -... + ... ``` You can customize this text by modifying the config value for `optional_hint_text`. @@ -102,17 +120,19 @@ a form group inline, set the `inline` attribute to `true`. ``` -The `form-group-inline` utility class provided by this package splits group into a grid, giving the label +The `form-group--inline` utility class provided by this package splits group into a grid, giving the label one column, and the input two columns across. If you use an input provided by this package, they default to full width, but you can limit the width by utilizing a `max-w-*` utility class from tailwind on the element. ### Inline Group Borders -As of v4, by default the form-group component will render a border on top of each inline form group component after the first group. +By default, the form-group component will render a border on top of each inline form group component after the first group. You can prevent this behavior by passing in `false` to the `border` attribute. ```html -... + + ... + ``` By default, the styles will add some padding to the label's column to center align it with the input, but that @@ -127,13 +147,106 @@ set the `is-checkbox-group` attribute to `true`, and it will not add padding to ## Margins -As of v4, the form-group component will now add a `mb-5` margin utility class to each form-group component, so each form-group has a little +The form-group component will now add a `mb-5` margin utility class to each form-group component, so each form-group has a bit of breathing room from each other. The last form-group child in a container will have no margin bottom because of the `last:mb-0` utility class. If you don't want margins to be added to each form-group, you can do the following: ```html -... + ... ``` > {tip} To help space your form elements evenly in a form, you could also use a `space-y-*` utility class > provided by tailwind on the wrapping element (usually `

    `). This **will take precedence** over the margin > utility class added by the component. + +## Label Ids + +Thanks to our `x-form-group` directive, the labels inside a form-group component will have their id scoped using Alpine's `x-id` functionality. That means +every time a component inside the form group references the label's id (`$id('fc-label')`), it will always receive the correct id. The most common use case for this +for the custom-select component which relies on it this for setting the `aria-labelledby` attribute. + +If you have a non-standard input, it is generally a best practice to set these accessibility attributes. Inside a form-group, you can always do the following the get +the label's id: + +```html + +
    ...
    +
    +``` + +Both the label, and the aria-labelledby attribute will have `fc-label-1` for the attribute value. + +## API Reference + +### props + +| prop | description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `name` | The name of the input element inside the form group | +| `inputId` | The ID of the input element inside the form group. Defaults to `name` if not set. Will be used for the `for` attribute on the label. | +| `label` | Text for a label to render in the form group. Set value to `false` to hide the label | +| `inline` | A boolean value indicating if the label and input should be inline with each other in a grid. Defaults to `false` | +| `showErrors` | A boolean indicating whether or not to show error states and messages for the input. Defaults to `true` | +| `helpText` | Helper text to display underneath the input and errors (if shown) | +| `isCheckboxGroup` | A boolean value, that if set to `true`, will remove all padding from the top of the input element area. Defaults to `false` | +| `marginBottom` | A boolean value to indicate the form group should apply a margin bottom if it is not the last child. Defaults to `true` | +| `border` | A boolean value to indicate that an inline form group should show a border if it is not the first child. Defaults to `true` | +| `hint` | Provide a "hint" text, such as "Optional" for the user. | +| `optional` | Provides an indication to the user that the input is optional. Will set the `hint` attribute to "Optional" if not explicitly set | + +### slots + +| slot | description | +| ---------- | ---------------------------------------------------------------------------------- | +| `hint` | Provide a "hint" text, such as "Optional" for the user. | +| `helpText` | Helper text to display underneath the input and errors (if shown) | +| `after` | Provides a place to put any custom markup towards the end of the main content area | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the form-group element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'form_group' => [ + // Apply a CSS class to the root form group element globally. + 'class' => null, + + // Apply a margin bottom by default to form groups (except for last child). + 'margin_bottom' => true, + + // Render a border on top of each form group by default. + // Does not render on first of type form groups in a container. + // This option only applies to inline form groups as well. + 'border' => true, + + // Make all form groups show the label inline with the input by default. + 'inline' => false, + + // Apply a CSS class to the form group label container globally. + 'label_container_class' => null, + + // Apply a CSS class to the form group content globally. + 'content_class' => null, + ], +], +``` + +### directives + +These directives are used internally by the component and aren't necessary for you to reach for yourself. + +**x-form-group** + +The main directive for the form group, and is applied to the root. This directive scopes the +id for a label using Alpine's `x-id` directive. + +**x-form-group:label** + +A directive used to attach a click event listener onto the label inside a form group. This click event listener will +give focus to a custom-select or quill rich text editor instance if one is present in the form group. diff --git a/docs/form/form.md b/docs/form/form.md index 5c66072..05f6c57 100644 --- a/docs/form/form.md +++ b/docs/form/form.md @@ -13,17 +13,15 @@ and CSRF directives and allows for easier to use syntax than the default HTML fo The most basic usage of the `form` component exists in encapsulating some form elements: ```html - - Form fields... - + Form fields... ``` This will output the following HTML: ```html - - - + + + Form fields...
    @@ -32,7 +30,7 @@ This will output the following HTML: By default, a `POST` HTTP method will be set. Of course, you can customize this. You can also enable spellcheck (remove the `spellcheck="false"` attribute that is set by default) as well: ```html - + Form fields... ``` @@ -40,10 +38,10 @@ By default, a `POST` HTTP method will be set. Of course, you can customize this. This will output the following HTML: ```html -
    - - - + + + + Form fields...
    ``` @@ -55,19 +53,33 @@ As you can see, a `_method` input was added since HTML tags only support `POST` To enable file uploads in a form you can make use of the `has-files` attribute: ```html - - Form fields... - + Form fields... ``` This will output the following HTML: ```html -
    - - + + + Form fields...
    ``` Now `file` input fields will be able to be submitted with the form. + +## API Reference + +### props + +| prop | description | +| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `action` | Server endpoint to submit the form to | +| `method` | Request method to use for the submission. Defaults to `POST` | +| `hasFiles` | A boolean indicating the form should submit files. Defaults to `false` | +| `spellcheck` | A boolean indicating the form should allow the browser to spellcheck the inputs inside of it. Defaults to `false` (spellcheck disabled on form) | diff --git a/docs/form/label.md b/docs/form/label.md index 3b16b5a..f101399 100644 --- a/docs/form/label.md +++ b/docs/form/label.md @@ -13,6 +13,21 @@ This isn't a component you will usually reach for, as in most cases you will pro want to use the `form-group` component to render the label and errors automatically for you, but this component is available to use for other use cases you may have. +> {note} All labels will be provided an id with Alpine's `$id` magic helper. This helps certain components like +> custom-select provide accurate accessibility attributes when in a form-group. + +## Requirements + +Since the label makes use of Alpine's `$id` magic helper, you will need Alpine.js installed. All labels will get the following attribute applied: + +```html +:id="$id('fc-label')" +``` + +If the ID is not setting on the label, ensure you are placing the label inside some kind of `x-data` scope. + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage The most basic usage of the component is as follows: @@ -28,3 +43,11 @@ provide your own label in the default slot: ```html My custom label ``` + +## API Reference + +### props + +| prop | description | +| ----- | ------------------------------------------------------- | +| `for` | The name (or id) of the input element the label is for. | diff --git a/docs/inputs/checkbox-group.md b/docs/inputs/checkbox-group.md index 40d5623..3514dd0 100644 --- a/docs/inputs/checkbox-group.md +++ b/docs/inputs/checkbox-group.md @@ -6,7 +6,7 @@ sort: 5 ## Introduction The checkbox group allows you to quickly group related checkboxes or radio buttons together in your forms. -This is not a replacement for the form-group component, and should be used inside of the form-group component +This is not a replacement for the form-group component, and should be used inside the form-group component in your forms. ## Basic Usage @@ -15,11 +15,13 @@ The most basic usage is like this: ```html - checkbox 1 - checkbox 2 + + ``` +This will stack the checkboxes on top of each other. + ## Inline Groups By default, the `checkbox-group` is designed to stack your checkboxes and radio inputs, but you can display them inline @@ -27,8 +29,8 @@ with each other, by setting the `stacked` attribute to `false`. This will displa ```html - checkbox 1 - checkbox 2 + + ``` @@ -37,7 +39,40 @@ with each other, by setting the `stacked` attribute to `false`. This will displa By default, the checkbox-group renders checkboxes in rows with 3 columns when it is rendered inline. To render a different amount of columns, you can specify the `grid-cols` attribute: ```html - - ... - + ... +``` + +## Sizing + +For convenience, you can size all the radio or checkbox elements the same by using the `inputSize` attribute. If no size is provided, it will use +the config value for radios and checkboxes. + +```html +... +``` + +For more information on the sizing, checkout the [Sizing](/docs/laravel-form-components/{version}/inputs/checkbox#user-content-sizing) documentation for checkboxes. + +## API Reference + +### props + +| prop | description | +| ----------- | ----------------------------------------------------------------------------------------------------------- | +| `stacked` | A boolean value indicating if the elements should be stacked, or placed in grid columns. Defaults to `true` | +| `gridCols` | The number of grid columns to use for the elements. Requires `stacked` to be `true`. Defaults to `3` | +| `inputSize` | The size to make all child inputs. Defaults to the config size for choice. | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the checkbox-group element. + +```php +'defaults' => [ + 'choice' => [ + // Supported: 'sm', 'md', 'lg' (defaults to 'sm' if null) + 'size' => null, + ], +], ``` diff --git a/docs/inputs/checkbox.md b/docs/inputs/checkbox.md index 8066461..73081a4 100644 --- a/docs/inputs/checkbox.md +++ b/docs/inputs/checkbox.md @@ -22,40 +22,136 @@ The most basic usage of the component exists in setting a `name` attribute: You can easily add a label to a checkbox by using the `label` attribute, or by using the `default slot`: Via prop: + ```html ``` Via slot: + ```html - - Remember me - + Remember me ``` +By default, the label will be placed on the **right** if the checkbox, however you can have it placed on the left side instead by setting the `labelLeft` attribute +to `true`. + +```html + +``` + +This setting can be set globally in the [config](#user-content-config) or on a per-element basis like shown above. + ## Description -You can also add a description (help text) for a checkbox by either setting the `description` attribute or +You can also add a description (help text) for a checkbox by either setting the `description` attribute or by using the `description` slot. Via prop: + ```html - + ``` ```html - Keep me logged in + Keep me logged in ``` +By default, this will render the description underneath the label, however you can have it render it inline with the label by setting +the `inlineDescription` attribute to `true`. + +```html + +``` + +This will work on both left and right aligned labels, and can be set globally in the [config](#user-content-config) or on a per-element +basis like shown above. + ## Old Values The `checkbox` component also supports checked values that were set. For example, you might want to apply some validation in the backend and make sure the user doesn't lose their input data when you show them the form again with the validation errors. -When re-rendering the form, the `checkbox` component will remember the checked value (when not using `wire:model`): +When re-rendering the form, the `checkbox` component will remember the checked value (when not using `wire:model` or `x-model`): ```html ``` + +## Sizing + +The package offers three different sizes for checkbox and radio elements. By default, they will render as the "sm" size, but this can be changed globally +in the config file under `defaults.choice.size`. You can also set this on a per-element setting using the `size` attribute: + +```html + +``` + +The input sizes are utility classes, which means you can prefix them with screen size breakpoints for further flexibility on sizing your inputs. For example, if you want +your checkboxes to normally be the "sm" size, but on medium size screens and up, you want them to be "lg", you can set your size on the `container-class` prop: + +```html + +``` + +## API Reference + +### props + +| prop | description | +| ------------------- | -------------------------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to name. | +| `value` | Initial value of the input | +| `label` | A label to display next to the checkbox | +| `description` | Help text to display underneath the label | +| `checked` | A boolean value to indicate the checkbox should be checked | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `size` | Set the size of the checkbox element. Supported: `sm`, `md`, `lg`. Defaults to `sm` | +| `inlineDescription` | A boolean value indicating the description should be inline with the label. Defaults to `false` | +| `labelLeft` | A boolean value indicating the label should be rendered to the left of the checkbox. Defaults to `false` | +| `extraAttributes` | Pass an array of HTML attributes to render on the checkbox | + +### slots + +| slot | description | +| ------------- | ------------------------------------------------------------------------------ | +| `label` | A label to display next to the checkbox. Default slot accomplishes same thing. | +| `description` | Help text to display underneath the label. | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the checkbox element. + +```php +'defaults' => [ + 'choice' => [ + // Automatically apply a CSS class to each checkbox/radio container. + 'container_class' => null, + + // Automatically apply a CSS class to each checkbox/radio input. + 'input_class' => null, + + // Supported: 'sm', 'md', 'lg' (defaults to 'sm' if null) + 'size' => null, + + // Show the description inline with the label by default. + 'inline_description' => false, + + // Render the label on the left side of the checkbox/radio by default. + 'label_left' => false, + ], +], +``` diff --git a/docs/inputs/date-picker.md b/docs/inputs/date-picker.md index 640ee72..cbb0723 100644 --- a/docs/inputs/date-picker.md +++ b/docs/inputs/date-picker.md @@ -10,16 +10,17 @@ By using it, you can simply add a date and/or time picker to your form with one ## Installation -While the `date-picker` component works out-of-the-box when you've [set the directives](/docs/laravel-form-components/installation#directives), -we recommend that you install and compile the JavaScript libraries before you deploy to production: +The `date-picker` component requires the following third-party libraries to work correctly: -- [Alpine.js](https://github.com/alpinejs/alpine) `^2.8` -- [Flatpickr](https://flatpickr.js.org/) `^4.6.9` +- Alpine.js +- Flatpickr + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. Make sure you import flatpickr as `flatpickr` in your JavaScript, and make sure it's available globally: ```js -import flatpickr from 'flatpickr'; +import flatpickr from "flatpickr"; window.flatpickr = flatpickr; ``` @@ -29,10 +30,10 @@ window.flatpickr = flatpickr; If you pull the `flatpickr` package in via npm, you should import the styles into your stylesheet: ```css -@import 'flatpickr/dist/flatpickr.min.css'; +@import "flatpickr/dist/flatpickr.min.css"; ``` -> {note} Be sure these styles are imported before the styles for this package so we can override the styles for flatpickr correctly. +> {note} Be sure these styles are imported before the styles for this package, so we can override the styles for flatpickr correctly. ## Basic Usage @@ -46,34 +47,35 @@ The component sets a couple of nice defaults for your date picker. The `placeholder` is automatically set the default format used by flatpickr, but this can easily be changed by passing in the placeholder to the component. -By default, the date picker is set to only open when you click the toggle icon, and it allows +By default, the date picker is set to open when you click the toggle icon, and it allows you to type in the input as well. There is also a clear icon that gets inserted by default as well. All of these options can be toggled on the component. ## Toggle Button By default, a toggle button with a calendar icon is prepended to the input. Clicking this button will show the calendar -that flatpickr generates. If you want to prevent the button/icon from being displayed, you can set the value to `false`: +that flatpickr generates. If you want to prevent the button/icon from being displayed, you can set the value to an empty string: ```html - + ``` -> {note} If you disable the toggle button, be sure to set `click-opens` to `true` on the component. +> {note} If you disable the toggle button, be sure to set `click-opens` to `true` on the component. It is set to `true` by default in the config, unless you modified +> that value. -> {tip} You can also change the icon that is used for the toggle button either by setting the `toggle-icon` attribute, or by changing -> it globally [in the config](https://github.com/rawilk/laravel-form-components/blob/{branch}/config/form-components.php#L103). +> {tip} You can change the icon that is used for the toggle button either by setting the `toggle-icon` attribute, or by changing +> it globally [in the config](#user-content-config). ## Clearing -The date picker component provides a way to clear the selected date out of the box. All you need to do is set `clearable` +The date picker component provides a way to clear the selected date out-of-the-box. All you need to do is set `clearable` to `true` and an icon for clearing the input will be appended to the input. ```html ``` -The icon defaults to `heroicon-o-x-circle`, but you can easily customize this icon either [in the config](https://github.com/rawilk/laravel-form-components/blob/{branch}/config/form-components.php#L109), or by setting the `clear-icon` attribute to the icon you want. +The icon defaults to `heroicon-m-x-mark`, but you can easily customize this icon either [in the config](#user-content-config), or by setting the `clear-icon` attribute to the icon you want. ## Options @@ -86,64 +88,199 @@ array with scalar values. Below is an example where we set mode to "multiple" in For a full reference of all options, please consult [the flatpickr documentation](https://flatpickr.js.org/options/). +> {tip} In this example, we set mode in the options array, however the component also accepts a prop called `mode`, which defaults to `single`. + ### Click Opens For convenience, we have added a `click-opens` (`clickOpens` option) boolean attribute to the component to easily toggle whether clicking on the input should open the picker. By default, the component sets this value to `false` to allow typing into the input. If you enable this option, be aware that you might lose the ability to type into the input. +This can be set globally and on a per-element basis. + ### Allow Input The boolean `allow-input` (`allowInput` option) attribute has been added for convenience to easily toggle whether the user is allowed to enter a date directly into the input field. By default, the component sets this value to `true`. +This can be set globally and on a per-element basis. + ### Enable Time The boolean `enable-time` (`enableTime` option) attribute has been added for convenience to allow for a time picker to be available as well. By default, the component sets this value to `false`. +This can be set globally and on a per-element basis. + ### Format If you pass a format (e.g. `Y-m-d`) attribute to the component, it will set the `dateFormat` option on flatpickr. This option defines how the date is displayed in the input, but **also how it is sent to the server**. +This can be set globally and on a per-element basis. + > {note} Please note that only scalar values are supported. You cannot use any JavaScript language specific options > like callbacks. ## Callbacks -Since the `options` attribute only accepts scalar values, the component offers a `optionsSlot` slot that will allow you to -specify any option callbacks you need to: +Since the `options` attribute only accepts scalar values, the component offers a `config` slot that will allow you to +specify any option callbacks you need to. The slot will be rendered inside a JavaScript object which will be passed to our +component JavaScript. ```html - - onChange: (selectedDates, dateStr, instance) => { - // ... - } - + + onChange: (selectedDates, dateStr, instance) => { // ... } + ``` In the example above, we are injecting a callback for the `onChange` event fired by flatpickr into the flatpickr options object. For more information on the callbacks available, please consult [the events api](https://flatpickr.js.org/events/). -By default, the date picker component defines a callback for the `onOpen` event fired by flatpickr. As of version `6.0.1`, you may utilize -the `onOpen` slot to add your own callback function if needed on the component. +> {note} The `onChange` callback is for demonstration purposes only. Our JavaScript is defining a callback for that event already, so it is not +> advised to define your own callback for it. + +By default, the date picker component defines a callback for the `onOpen` event fired by flatpickr. Luckily, flatpickr allows an array of callbacks +to be used for this event. You may define your own callbacks for `onOpen` in the `config` slot, and our JavaScript append them to the callbacks array for +the event. ```html - - function (selectedDates, dateStr, instance) { - // do something - }, - + + onOpen: [ function (selectedDates, dateStr, instance) { // do something + }, ], + ``` +In the example above, the `instance` parameter refers to the `flatpickr` instance. + ## Addons Like the other inputs, the date picker can also have leading and trailing addons, however by default you cannot add them. To add leading addons, you must disable the toggle icon, and for trailing addons, you must set `clearable` to `false`. -See the [input documentation](/docs/laravel-form-components/{version}/inputs/input#addons) for more information. +See the [addons documentation](/docs/laravel-form-components/{version}/advanced-usage/addons) for more information. + +## End Slot + +The `end` slot will allow you to render any kind of HTML you need at the very end of the component's markup. Since it is rendered +inside the `x-data` markup, you will have access to the Alpine component data, as well as the `$datePicker` Alpine magic. This slot +shouldn't normally be required, but it's available should feel the need to get creative with your component logic. + +See [$datePicker](#user-content-datepicker) for more info on the magic variable. + +## API Reference + +### props + +| prop | description | +| --------------------- | ------------------------------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to name. | +| `type` | Type of input. Defaults to `text` | +| `value` | Value of the input. Gets omitted if `wire:model` or `x-model` is present | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `size` | Define a size for the input. Default size is `md` | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the input | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | +| `options` | An array of scalar values to configure flatpickr | +| `mode` | The mode of date selection. Supports `single`, `multiple`, and `range`. Defaults to `single` | +| `clickOpens` | Allow the date picker to open when the input element is clicked on. | +| `allowInput` | Allow user to enter a date into the input element directly. | +| `enableTime` | Show a time picker | +| `format` | Define a format for the date to send to the server | +| `toggleIcon` | A name for an icon component to show for the toggle button | +| `clearable` | If `true`, a button will be appended to the input to clear the value. Requires `clearIcon` to be set as well. | +| `clearIcon` | The name of an icon component to display in the clear button | +| `placeholder` | Text to show as a placeholder. Defaults to a translation key in package's translations. | + +### slots + +| slot | description | +| --------------------- | ----------------------------------------------------------------------------------------------------- | +| `before` | Render HTML before the input and/or leading addons | +| `after` | Render HTML after the input and/or trailing addons | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | +| `config` | Allows you to define JavaScript callbacks for flatpickr. Slot is rendered inside a JavaScript object. | +| `end` | Render any kind of HTML at the end of the component markup, but inside of the `x-data` scope. | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the date picker element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + + // Classes applied by default to input parent div. + // Will also apply to select. + 'container_class' => null, + + // Base input classes applied by default. + 'input_class' => null, + ], + + 'date_picker' => [ + // Allow date picker to open from clicking on the input by default. + 'click_opens' => false, + + // Allow user to modify the text of the input by default. + 'allow_input' => true, + + // Enable the time picker by default. + 'enable_time' => false, + + // Set the default date format. (defaults to y-m-d) + 'format' => null, + + // Set an icon to show on the date picker for an "open" button by default. + // Set to null to hide it. + 'toggle_icon' => 'heroicon-m-calendar', + + // Allow date pickers to be cleared by a clear button by default. + 'clearable' => true, + + // Set an icon to show on the date picker's clear button by default. + 'clear_icon' => 'heroicon-m-x-mark', + + // Set the default placeholder text for the date picker. + // For best results, use a translation key as it will be translated automatically by the component. + 'placeholder' => 'form-components::messages.date_picker_placeholder', + ], +], +``` + +### $datePicker + +A magic variable that exposes information about the current state of the date picker. Under normal use, +you shouldn't need to access this variable. The `end` slot is a convenient way to access it. + +| Property | Description | +| ------------ | ------------------------------------------------------------ | +| `isDisabled` | A boolean indicating if the date picker is disabled | +| `flatpickr` | Exposes the `flatpickr` instance on the component | +| `hasValue` | A boolean indicating if the date picker has a value selected | +| `open()` | A callable that opens up the date picker | diff --git a/docs/inputs/email.md b/docs/inputs/email.md index 5f0bfb8..29b983a 100644 --- a/docs/inputs/email.md +++ b/docs/inputs/email.md @@ -17,7 +17,7 @@ The most basic usage of the component is like this: ``` -By default an `email` type will be set for the input field as well as an `id` that allows it to be +By default, an `email` type will be set for the input field as well as an `id` that allows it to be easily referenced by a `label` element. Besides this, the email element behaves exactly the same as the [input component](/docs/laravel-form-components/{version}/inputs/input). diff --git a/docs/inputs/input.md b/docs/inputs/input.md index fc706b7..b54a30b 100644 --- a/docs/inputs/input.md +++ b/docs/inputs/input.md @@ -34,10 +34,16 @@ lose their input data when you show the form again with the validation errors. When re-rendering the form, the `input` component will remember the old value. ```html - + ``` -> {note} This doesn't apply when using `wire:model`, as livewire will take care of setting the value instead +> {note} This doesn't apply when using `wire:model` or `x-model`, as livewire or alpine will take care of setting the value instead > and the component will not set the `value` attribute itself. ## Error Handling @@ -48,18 +54,19 @@ When there are errors for a field, the `aria-invalid` and `aria-describedby` att ```html
    -
    ``` The actual error message won't be rendered from the input component itself, but it can be automatically rendered for you -by wrapping the `` component inside of a `` component. Please refer to the [form-group documentation](/docs/laravel-form-components/{version}/form/form-group#error-handling) for more information. +by wrapping the `` component inside an `` component. Please refer to the [form-group documentation](/docs/laravel-form-components/{version}/form/form-group#user-content-error-handling) for more information. The `aria-describedby` attribute takes the `name` attribute and appends `-error` to it, which will be the id given to the error message rendered by the `` component. If you already have `aria-describedby` set on the input, the attribute value will be merged with the error attribute value. @@ -70,93 +77,102 @@ If you don't want error attributes to be added to the input, you may disable the ``` -## Addons - -Both leading and trailing addons can easily be added to the input either by use of props or slots. When rendering the input, -only one type of leading addon and one type of trailing addon will be rendered at a time. - -### Leading Addon - -A leading addon will be rendered as text on top of a light gray background at the beginning of the input. To render a leading -addon, specify the text either in the `leading-addon` attribute or the `leadingAddon` slot. - -Via prop: -```html - -``` - -Via slot: -```html - - https:// - -``` - -### Inline Addon - -Inline addon is similar to leading addon, however there is no background behind the text. You are also responsible -for setting the left padding of the input to allow for enough room for your text to fit at the beginning of the -input (defaults to `pl-16 sm:pl-14`) by setting the `inline-addon-padding` attribute. - -You can set the inline addon by using the `inline-addon` attribute or the `inlineAddon` slot. +> {tip} If you find yourself setting the `show-errors` prop to `false` every time, you may set the global `show_errors` config setting to `false` under the `defaults` +> configuration key. -Via prop: -```html - -``` - -Via slot: -```html - - https:// - -``` +## Addons -### Leading Icon +The input component supports all the available addons this package offers. Header over to the [Addons](/docs/laravel-form-components/{version}/advanced-usage/addons) documentation +for an in-depth guide on how to use them. -Instead of text, you can prepend an icon to the input instead. The package is styled for -[blade heroicon svgs](https://github.com/blade-ui-kit/blade-heroicons), but you are free -to use whatever icons you want to. +## Sizing -To prepend an icon, use the `leadingIcon` slot: +The package offers three input sizes configured for you out-of-the-box: sm, md, and lg. Inputs by default are configured to render as a "md" sized input, but this can be changed +globally in the config file under `defaults.input.size`. This setting will also affect textareas, native selects, native file upload, and the date picker element. You can also +set the size on a per-element basis using the `size` prop: ```html - - - icon svg... - - + ``` -### Trailing Addon - -Like the inline addon, the trailing addon will add text directly inside of the input, but this time at the right -side of the input. Also like the inline addon, you will need to specify the padding yourself (defaults to `pr-12`) -by using the `trailing-addon-padding` attribute. +The input sizes are utility classes, which means you can prefix them with screen size breakpoints for further flexibility on sizing your inputs. For example, if you want +your inputs to normally be the "md" size, but on medium size screens and up, you want them to be "lg", you can set your size on the `container-class` prop: -You can add a trailing addon by using either the `trailing-addon` attribute or the `trailingAddon` slot. - -Via prop: ```html - + ``` -Via slot: -```html - - USD - +If you want to use your own size utility classes, you will need to define them in your app's CSS. For a quick override on the amount of padding given to each size, you can override the following CSS +variables: + +```css +:root { + --input-padding-y: theme("spacing[2.5]"); + --input-padding-x: theme("spacing.3"); + --input-padding-y-sm: theme("spacing.2"); + --input-padding-x-sm: theme("spacing.2"); + --input-padding-y-lg: theme("spacing.4"); + --input-padding-x-lg: theme("spacing.4"); +} ``` -### Trailing Icon - -You can append an icon to an input similar to prepending one. You can do so using the `trailingIcon` slot: - -```html - - search icon... - +## API Reference + +### props + +| prop | description | +| --------------------- | ----------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to `name`. | +| `type` | Type of input. Defaults to `text` | +| `value` | Value of the input. Gets omitted if `wire:model` or `x-model` is present | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `size` | Define a size for the input. Default size is `md` | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the input | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | + +### slots + +| slot | description | +| --------------------- | -------------------------------------------------- | +| `before` | Render HTML before the input and/or leading addons | +| `after` | Render HTML after the input and/or trailing addons | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the input element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + + // Classes applied by default to input parent div. + // Will also apply to select. + 'container_class' => null, + + // Base input classes applied by default. + 'input_class' => null, + ], +], ``` - -> {tip} The leading and trailing addons can also be applied the same way to the textarea, select, email, and password -> inputs provided by this package. diff --git a/docs/inputs/password.md b/docs/inputs/password.md index 0553cb3..c66b495 100644 --- a/docs/inputs/password.md +++ b/docs/inputs/password.md @@ -11,25 +11,10 @@ The `password` component offers an easy way to set up a password input field for By default, the component shows a toggle icon, which allows the user to show and hide the password. The use of this feature requires: -- AlpineJS -- Blade Heroicons (different icons can be specified in the config file) -- Proper tailwind configuration - -As of version 1.4.10, you will need to specify a `focus-within` utility for the `box-shadow` styles so that focus can be properly shown -on the password inputs that are toggleable. In your `tailwind.config.js` file, you should add the following variant to it: - -```js -module.exports = { - // ... - variants: { - boxShadow: ['responsive', 'hover', 'focus', 'focus-within'], - }, -} -``` - -> {note} If you are using Tailwind's JIT, you shouldn't need to specify these variants anymore. +- Alpine.js +- Blade Heroicons (different icons can be specified in the config file) -See the [Tailwind documentation](https://tailwindcss.com/docs/pseudo-class-variants#focus-within) for more information. +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. ## Basic Usage @@ -39,28 +24,36 @@ The most basic usage of the component is as follows: ``` -The show and hide icons can be configured via config: +## Icons -```php -'components' => [ - ... - 'password' => [ - ... - 'show_password_icon' => 'heroicon-s-eye', - 'hide_password_icon' => 'heroicon-o-eye-off', - ], - ... -], +The show and hide icons shown on the toggle button can be set using the `showPasswordIcon` and `hidePasswordIcon` props on the component. By default, they will be set to the value on the config +file for the password input; see [config](#user-content-config) below. + +```html + ``` ## Show Password Toggle If you do not want to show the toggle icon for the input, you can disable it by setting `show-toggle` to `false`. You should also disable it if you don't have alpine or blade heroicons installed. +This can also be done globally via config; see [config](#user-content-config) below. ```html ``` +## Initially Show Password + +If you don't want the password to be masked when the input is rendered for the first time, you may pass in `true` for the `intiallyShowPassword` prop. + +```html + +``` + ## Old Values Unlike the other inputs, the password component will not set the value unless the password is flashed to the session by your backend. @@ -71,4 +64,82 @@ Like the other inputs, the password input can also have leading addons, but sinc includes a password toggle as a trailing icon addon, you are not able to add a trailing addon to the password input. If you need a trailing addon, you should use the input component instead. -See the [input documentation](/docs/laravel-form-components/{version}/inputs/input#addons) for more information. +See the [addons documentation](/docs/laravel-form-components/{version}/advanced-usage/addons) for more information. + +## API Reference + +### props + +| prop | description | +| ----------------------- | --------------------------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to name. | +| `type` | Type of input. Defaults to `text` | +| `value` | Value of the input. Gets omitted if `wire:model` or `x-model` is present | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `size` | Define a size for the input. Default size is `md` | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the input | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | +| `showToggle` | A boolean value to indicate whether or not the toggle button should be shown. Defaults to config value. | +| `showPasswordIcon` | A name of the icon to show when the password is masked. Defaults to config value. | +| `hidePasswordIcon` | A name of the icon to show when the password is not masked. Defaults to config value. | +| `initiallyShowPassword` | A boolean value indicating if the password should be masked or not on initial render. Defaults to `false` | + +> {note} If `showToggle` is `true`, the password component will **not** render any trailing addons, as it needs that spot for the toggle button. + +### slots + +| slot | description | +| --------------------- | -------------------------------------------------- | +| `before` | Render HTML before the input and/or leading addons | +| `after` | Render HTML after the input and/or trailing addons | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the password element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + + // Classes applied by default to input parent div. + // Will also apply to select. + 'container_class' => null, + + // Base input classes applied by default. + 'input_class' => null, + ], + + 'password' => [ + // Show the password reveal button by default. + 'show_toggle' => true, + + // Icon shown when password is hidden. + 'show_icon' => 'heroicon-m-eye', + + // Icon shown when password is revealed. + 'hide_icon' => 'heroicon-m-eye-slash', + ], +], +``` diff --git a/docs/inputs/radio.md b/docs/inputs/radio.md index f12eec6..4a1f5ce 100644 --- a/docs/inputs/radio.md +++ b/docs/inputs/radio.md @@ -23,35 +23,61 @@ The most basic usage of the component exists in setting a `name` attribute: You can easily add a label to a radio by using the `label` attribute, or by using the `default slot`: Via prop: + ```html ``` Via slot: + ```html - - Tier 1 - - - Tier 2 - + Tier 1 + Tier 2 +``` + +By default, the label will be placed on the **right** if the radio, however you can have it placed on the left side instead by setting the `labelLeft` attribute +to `true`. + +```html + ``` ## Description -You can also add a description (help text) for a radio by either setting the `description` attribute or +You can also add a description (help text) for a radio by either setting the `description` attribute or by using the `description` slot. Via prop: + ```html - + ``` ```html - - Our most basic tier - + + Our most basic tier + +``` + +By default, this will render the description underneath the label, however you can have it render it inline with the label by setting +the `inlineDescription` attribute to `true`. + +```html + ``` ## Old Values @@ -64,3 +90,24 @@ When re-rendering the form, the `radio` component will remember the checked valu ```html ``` + +## Sizing + +The package offers three different sizes for checkbox and radio elements. By default, they will render as the "sm" size, but this can be changed globally +in the config file under `defaults.choice.size`. You can also set this on a per-element setting using the `size` attribute: + +```html + +``` + +The input sizes are utility classes, which means you can prefix them with screen size breakpoints for further flexibility on sizing your inputs. For example, if you want +your radios to normally be the "sm" size, but on medium size screens and up, you want them to be "lg", you can set your size on the `container-class` prop: + +```html + +``` + +## API Reference + +Since the radio component is just an extension of checkbox, their API is the same. Checkout the full +[Checkbox API Reference](/docs/laravel-form-components/{version}/inputs/checkbox#user-content-api-reference) for more information. diff --git a/docs/inputs/switch-toggle.md b/docs/inputs/switch-toggle.md index 1fa44e9..630cd75 100644 --- a/docs/inputs/switch-toggle.md +++ b/docs/inputs/switch-toggle.md @@ -7,15 +7,18 @@ sort: 9 The `switch-toggle` component offers an easy alternative to a traditional checkbox and is heavily based on the [Tailwind UI toggle component](https://tailwindui.com/components/application-ui/forms/toggles). The -switch toggle acts like a checkbox, however it allows for an "off" value and an "on" value; see [custom on and off values](#custom-on-and-off-values) -for more info. +switch toggle acts like a checkbox, however it's mostly used for an on/off state. ## Installation -While the `switch-toggle` component works out-of-the-box when you've [set the directive](/docs/laravel-form-components/{version}/installation#directives), -we recommend that you install and compile the JavaScript libraries before you deploy to production: +The `switch-toggle` component requires the following third-party libraries to work properly: -- [Alpine.js](https://github.com/alpinejs/alpine) `^2.8` +- Alpine.js + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + +If you're going to use different colors on the switch, be sure to include the `switch-toggle` plugin in your tailwind config. See [Plugins](/docs/laravel-form-components/{version}/advanced-usage/customizing-css#user-content-plugins) +for more information. ## Basic Usage @@ -35,18 +38,33 @@ You can easily add a label to the switch toggle by using the `label` attribute: ``` -This will render a label containing the text "Notifications on" to the right side of the switch. +This will render a label containing the text "Notifications on" to the right side of the switch. You can also use the default slot +to render the label as well: + +```html + Notifications on +``` ### Left aligned labels -You can also render labels on the left of switch by setting `label-position` to `left`: +You can also render labels on the left of switch by using the `labelLeft` attribute. ```html - + ``` Now "Notifications on" will be rendered to the left of the switch. +### Multiple Labels + +The component allows for labels to be placed on both the left and right side of the switch at the same time. + +```html + +``` + +This will render "Off" to the left, and "On" to the right. + ## Handling values The switch toggle component offers support for both `wire:model` and `wire:model.defer` right out of the box, and is the recommended way @@ -54,9 +72,14 @@ to use this component when you are using Laravel Livewire. Behind-the-scenes, th from livewire to bind the value to a local variable on the component. ```html - + ``` +> {tip} `x-model` can be used instead if you're not using Livewire in the form. + For non-livewire forms, you may also give the component a `value` to use for the initial value, but be sure to include a `name` attribute so that your server can receive the value from the switch in a normal form submission. @@ -64,16 +87,11 @@ can receive the value from the switch in a normal form submission. ``` -When the component is given a name attribute, it will render a hidden input so that the current value of the component is passed on to the server via a form submission. -The hidden input rendered from the example above will look like this: - -```html - -``` +> {note} Only true/false values are supported for the on/off values when used this way. ### Custom on and off values -The switch toggle is not limited to `true` and `false` values for its respective "on" and "off" values; it can use strings and integer values as well: +The switch toggle is not limited to `true` and `false` values for its respective on and off states; it can use strings and integer values as well: ```html @@ -89,7 +107,7 @@ Different size and style variations of the switch may be rendered out-of-the-box Based on the [short toggle](https://tailwindui.com/components/application-ui/forms/toggles#component-b3e0a15571300f79fced5845f97fa972) example from Tailwind UI, the short toggle will make the size of the circle on the bar larger than the height of the bar. All you need to do for this style is set -the `short` flag to `true`: +the `short` attribute to `true`: ```html @@ -97,49 +115,120 @@ the `short` flag to `true`: ### Sizing -Both the simple and short toggle variations allow for different sizing out-of-the-box. Simply pass in a `size` to the component to re-size it: +If you're not using the `short` variation, you can adjust the size of the switch via the `size` attribute. The currently supported sizes +are: `sm`, `md`, `lg`, with `md` being the default. ```html ``` -Here are the sizes the package provides by default for each variation: - -**Simple**: -- sm -- base (default) -- lg - -**Short**: -- base (default) -- lg - These sizes also come in responsive variants, so if you wanted the switch small on small screens, but large on larger screens, you could do something like this: ```html ``` -You are free to add your own sizes in your own stylesheets. Just reference the [switch toggle styles](https://github.com/rawilk/laravel-form-components/blob/{branch}/resources/sass/utils/_switch.scss#L126) for guidance. - ## Icons Based on the [toggle with icon](https://tailwindui.com/components/application-ui/forms/toggles#component-bcaf782196186836b6ea686e7096e734) from Tailwind UI, the switch toggle component allows you to specify icons to display on the button for both "on" and "off" states: +```html + +``` + +In this example, you will see an "x" icon when the switch is "off", and a checkmark icon when the switch is "on". + +> {note} This example requires the +> [blade heroicon](https://github.com/blade-ui-kit/blade-heroicons) package. + +You may also render the icons via slot instead if you prefer: + ```html - - - - - - - + + + + + + + ``` -In this example, you will see an "x" icon when the switch is "off", and a checkmark icon when the switch is "on". +> {note} Icons are not supported when the `short` attribute is set to `true`. + +## Colors + +By default, the switch-toggle component is configured to show a blue background when it is in an "on" state. Given you have the `switch-toggle` Tailwind plugin included in your tailwind config +file, you will be able to use any of your application's configured colors for the switch using the `color` attribute. -> {note} This example requires the -[blade heroicon](https://github.com/blade-ui-kit/blade-heroicons) package. +```html + +``` + +## API Reference + +### props + +| prop | description | +| ----------------- | --------------------------------------------------------------------------------- | +| `name` | The name of the input | +| `id` | The id of the input. Defaults to `name` | +| `value` | The initial value of the input. Disregarded if `wire:model` or `x-model` present. | +| `onValue` | The value for when the switch is "on". Defaults to `true` | +| `offValue` | The value for when the switch is "off". Defaults to `false` | +| `label` | Text to display to the right of the switch. | +| `labelLeft` | Text to display to the left of the switch. | +| `containerClass` | A CSS class to apply to the **container** of the switch. | +| `disabled` | Disable the switch | +| `size` | The size of the switch. Defaults to `md` | +| `color` | The color of the switch when it is "on". Defaults to blue | +| `onIcon` | An icon to display on the switch when it is in an "on" state | +| `offIcon` | An icon to display on the switch when it is in an "off" state | +| `short` | Display switch as the "short" style. Sizing does not apply to this style. | +| `extraAttributes` | Pass an array of attributes to apply to the input | + +### slots + +| slot | description | +| ----------- | ------------------------------------------------------------- | +| `label` | Text to display to the right of the switch. | +| `labelLeft` | Text to display to the left of the switch. | +| `onIcon` | An icon to display on the switch when it is in an "on" state | +| `offIcon` | An icon to display on the switch when it is in an "off" state | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the switch-toggle element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'switch_toggle' => [ + // Apply a CSS class to the label that contains the switch toggle globally. + 'container_class' => null, + + // Apply a CSS class to the switch toggle (not the actual input element) globally. + 'input_class' => null, + + // Set the default size of the switch toggle. + // Supported: 'sm', 'md', 'lg', (default is 'md') + 'size' => null, + + // Set the default color of the switch toggle. (e.g. "blue", "red", "green", etc.) + 'color' => null, + + // Set the default icon to show when the switch is in an "on" state. + 'on_icon' => null, + + // Set the default icon to show when the switch is in an "off" state. + 'off_icon' => null, + ], +], +``` diff --git a/docs/inputs/textarea.md b/docs/inputs/textarea.md index 782fcfe..e4da5fd 100644 --- a/docs/inputs/textarea.md +++ b/docs/inputs/textarea.md @@ -9,6 +9,14 @@ The `textarea` component offers an easy way to set up a textarea field for your By simply setting its `name` attribute it also automatically defines your `id` and makes sure old values are respected. +## Requirements + +If you want to take advantage of the auto-resize functionality of the component, you will need the following installed: + +- Alpine.js + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage The most basic usage of the component exists by setting a `name` attribute: @@ -17,7 +25,7 @@ The most basic usage of the component exists by setting a `name` attribute: ``` -By default a `rows` attribute will be set for the textarea field as well as an `id` that allows +By default, a `rows` attribute will be set for the textarea field as well as an `id` that allows it to be easily referenced by a `label` element. Of course, you can overwrite all of these values as well: @@ -34,15 +42,92 @@ re-rendering the form, the `textarea` component will remember the old value: ```html
    - +
    ``` If you are using livewire, the textarea will allow livewire to set the value instead, however. -## Reference +## Auto Resize + +You can have the textarea auto-resize its height based on its content length. This is enabled by default in the config, but you +can either disable it there or on a per-element basis with the `autoResize` prop: + +```html + +``` + +Behind-the-scenes, the component will make use of our custom `x-textarea-resize` directive to handle automatically resizing the +textarea for you. + +## API Reference + +### props -Since the textarea component extends the [input component](/docs/laravel-form-components/{version}/inputs/input), you are able -to do a lot of the same things you can with the input element, such as error handling and addons. +| prop | description | +| --------------------- | ----------------------------------------------------------------------------------------- | +| `name` | Name of the textarea | +| `id` | Id of the input. Defaults to name. | +| `type` | Type of input. Defaults to `text` | +| `value` | Value of the input. Gets omitted if `wire:model` or `x-model` is present | +| `containerClass` | Defines a CSS class to apply to the **container** of the input | +| `size` | Define a size for the textarea. Default size is `md` | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the textarea | +| `leadingAddon` | Render text on the left of the textarea | +| `leadingIcon` | Render an icon on the left of the textarea | +| `inlineAddon` | Render text inside the textarea on the left | +| `trailingAddon` | Render text on the right of the textarea | +| `trailingInlineAddon` | Render text inside the textarea on the right | +| `trailingIcon` | Render an icon on the right of the textarea | +| `autoResize` | Resize the textarea automatically as the user types into it. Defaults to config value. | + +### slots + +| slot | description | +| --------------------- | ----------------------------------------------------- | +| `before` | Render HTML before the textarea and/or leading addons | +| `after` | Render HTML after the textarea and/or trailing addons | +| `leadingAddon` | Render text on the left of the textarea | +| `leadingIcon` | Render an icon on the left of the textarea | +| `inlineAddon` | Render text inside the textarea on the left | +| `trailingAddon` | Render text on the right of the textarea | +| `trailingInlineAddon` | Render text inside the textarea on the right | +| `trailingIcon` | Render an icon on the right of the textarea | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the textarea element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + + // Classes applied by default to input parent div. + // Will also apply to select. + 'container_class' => null, + + // Base input classes applied by default. + 'input_class' => null, + ], + + 'textarea' => [ + // How many rows should the textarea have by default. + 'rows' => 3, + + // Automatically resize the textarea based on content length. + 'auto_resize' => true, + ], +], +``` diff --git a/docs/installation.md b/docs/installation.md index c2d233c..a5e57be 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -6,7 +6,7 @@ sort: 3 ## Notice Most of the components in this package are based on examples from Tailwind UI. I have my own license for Tailwind UI, but you might not have one. -**Please do not use this package in your own projects without purchasing a Tailwind UI license**, or they'll have to tighten up the licensing +**Please do not use this package in your own projects without purchasing a Tailwind UI license**, or they'll have to tighten up the licensing, and you'll ruin the fun for everyone. Purchase a license here: [https://tailwindui.com/](https://tailwindui.com) @@ -24,140 +24,166 @@ composer require rawilk/laravel-form-components You may publish the config file via: ```bash -php artisan fc:publish +php artisan vendor:publish --tag="form-components-config" ``` [Click here](https://github.com/rawilk/laravel-form-components/blob/{branch}/config/form-components.php) to view the default configuration. -## Directives +## Assets -One of the biggest advantages to `laravel-form-components` is that almost all of its components come ready -out-of-the-box. To achieve this, Laravel Form Components makes use of CDNs from -any 3rd party library that a component might need. To make sure these CDNs are -included in your HTML, you can make use of the `@fcStyles` and `@fcScripts` directives. +### Package JavaScript -Place the `@fcStyles` in the `` before any of your other styles. Place the `@fcScripts` directive right before -your closing `` tag and **after** scripts from libraries like Livewire. +To take advantage of some components offered by the package, you will need to include the package's JavaScript (on every page that will be using them). +Add the following before the end `body` tag in your template. -> {note} The `@fcStyles` directives **does not** include styles generated by Laravel Form Components. You will still need to include -> those in [a stylesheet manually](#styling). - -If you would like to only link to the JavaScript necessary for some package components, such as the custom select component, you may -use the `@fcJavaScript` blade directive instead of `@fcScripts`. This is useful if you are compiling any third-party scripts -yourself, and is recommended in production. You should not use both directives together regardless of how you choose -to compile scripts. - -## Production - -Even though these directives allow you to get up and running with the components quickly, **we recommend that you compile the 3rd -party libraries that each component needs through an asset pipeline** (like [Laravel Mix](https://github.com/JeffreyWay/laravel-mix)). -By default, when your `app.debug` config option is disabled, the directives are also disabled for performance reasons. +```html + + ... @fcScripts + +``` -If you always want these directives to be executed, even when `app.debug` is disabled, you can force them to load the CDN -links by passing a `true` boolean: +You can alternatively use the self-closing tag syntax. ```html -@fcStyles(true) @fcScripts(true) + + ... + + + ``` -Libraries are only loaded for components that are enabled through the `components` config option. You can learn more about -[disabling specific components](#components) below. +> {note} Be sure to include the scripts after Livewire's scripts if you're using it. -## Views +### Third-Party Assets -You may override the views, by publishing the package's views: +A few of the components in this package rely on third-party scripts and styles to work properly. Do the following to install all of them, or pick and choose +which ones to install if you're not going to use all the components in this package. ```bash -php artisan fc:publish --views +npm install -D @alpinejs/focus +npm install -D @popperjs/core +npm install -D @tailwindcss/forms +npm install -D alpinejs +npm install -D filepond +npm install -D flatpickr +npm install -D quill +npm install -D tailwindcss ``` -> {note} This will also publish the package's configuration as well. +> {note} `alpinejs` is required for any of the package's JavaScript to work, and `tailwindcss` and `@tailwindcss/forms` are required to style the components correctly. +> You will also need `@alpinejs/focus` for some functionality to work correctly in the custom select component. -## Styling +In your project's JavaScript, do the following: -You have a couple options for how you can use the UI components' CSS, depending on you and your project's needs: - -### Using Laravel Mix or Webpack with CSS-Loader +```js +import Alpine from "alpinejs"; +import flatpickr from "flatpickr"; +import Quill from "quill"; +import * as FilePond from "filepond"; +import { createPopper } from "@popperjs/core"; +import focus from "@alpinejs/focus"; -You can import the CSS files into your own stylesheets using `@import '../../vendor/rawilk/laravel-form-components/resources/css/index.css';'`. -This is assuming your stylesheet is located in the `./resources/css/` directory of your project. +Alpine.plugin(focus); -This will import all the package's styles into your project, however you are free to import only the stylesheets you need as well. They are all located -in the same directory as the `index.css` stylesheet. +window.flatpickr = flatpickr; +window.FilePond = FilePond; +window.Quill = Quill; +window.createPopper = createPopper; +window.Alpine = Alpine; -If you would like to customize the CSS we provide, head over to [the section on Customizing CSS](/docs/laravel-form-components/{version}/advanced-usage/customizing-css). +window.Alpine.start(); +``` -> {tip} If you are using Purge CSS or Tailwind's JIT compiler, you should check out the section on [Purge CSS](/docs/laravel-form-components/{version}/advanced-usage/customizing-css#purge-csstailwind-jit) -> to prevent styles from being lost in production or at compile time. +In your project's CSS, do the following for styling: -## Components +```css +@import "filepond/dist/filepond.min.css"; +@import "flatpickr/dist/flatpickr.min.css"; +@import "quill/dist/quill.snow.css"; -Even though all components come enabled out-of-the-box, you might just want to -only load the components you need in your app for performance reasons. To do so, -first [publish the config file](#configuration), then remove the components -you don't need from the `components` settings. +@tailwind base; +@tailwind components; +@tailwind utilities; +``` -You can also choose to use different classes for components. This allows you -to either extend or completely change the component's functionality by using a custom class -and/or view of your own. +> {tip} You are free to use a CDN version of any third-party assets as an alternative to loading them through npm. -### Component Namespace +### Package Styles -New in v6, the package also declares a `form-components` blade component namespace. This means that -for any component you may also use the `` syntax. For the `input` -component, you would use ``. If you choose to render the components -using this method, you can safely remove the component alias from the config, however there are two caveats to this: +Assuming your app CSS file is located in `/resources/css/app.css`, you can load in the package's styles like this: -1. You may not be able to override the component class definition any more if you remove the alias from the config. -2. Some components have an array of configuration options attached to their alias. Those arrays are referenced - by the component, so these aliases should not be removed or renamed. +```css +... + @import + "../../vendor/rawilk/laravel-form-components/resources/css/index.css"; +``` -## Component JavaScript +This will import all the package's styles into your stylesheet, however you are free to import only the stylesheets you need as well; they are all +located in same directory as the `index.css` stylesheet. -Some components, such as the [custom select component](/docs/laravel-form-components/{version}/selects/custom-select), require custom -JavaScript to run. The JavaScript is extracted to an external file since it is pretty substantial and should be minified. If -you are using any components that depend on this JavaScript, be sure you are pulling the scripts in through either the -`@fcJavaScript` or `@fcScripts` blade directives in your layout file. See [directives](#directives) for more information. +If you would like to customize the CSS we provide, head over to [the section on customizing CSS](/docs/laravel-form-components/{version}/advanced-usage/customizing-css). It's +also important to read over this section, as it will detail any Tailwind config requirements to get the styles working correctly. -## JavaScript Dependencies +## Views -For any external JavaScript dependency, we recommend you install them through npm or yarn, and then require them in your project's JavaScript. To install each of the dependencies this package makes use of, run this command in the terminal: +You may override any component's view by publishing them to your project: ```bash -npm install -D alpinejs @popperjs/core filepond flatpickr +php artisan vendor:publish --tag="form-components-views" ``` -> {tip} You can pick and choose which dependencies you need to install based on which components your project is actually using. +### Tailwind Configuration -In your JavaScript, add the following lines to pull each of the external dependencies you previously installed in: +Some custom configuration is necessary for the package's CSS to compile correctly, and for some components to be styled correctly. Head over to the +[customizing CSS](/docs/laravel-form-components/{version}/advanced-usage/customizing-css) docs for more information on configuring Tailwind. -```js -import Alpine from "alpinejs"; -import flatpickr from "flatpickr"; -import * as FilePond from "filepond"; -import { createPopper } from "@popperjs/core"; +## Components -window.flatpickr = flatpickr; -window.FilePond = FilePond; -window.createPopper = createPopper; -window.Alpine = Alpine; +Even though all components come enabled out-of-the-box, you might just want to +only load the components you need in your app for performance reasons. To do so, +first [publish the config file](#user-content-configuration), then remove the components +you don't need from the `components` settings. -Alpine.start(); -``` +You can also choose to use different classes for components. This allows you +to either extend or completely change the component's functionality by using a custom class +and/or view of your own. -### Dependency Styling +> {tip} If you remove an alias of a component, it will still be available under the `form-components::` component namespace. -Some of the dependencies this package has also have their own styling they provide. If you followed the directions above for installing the JavaScript, you can easily pull in their styles into your project as well: +### Component Namespace -```css -/* app.css */ -@import "filepond/dist/filepond.min.css"; -@import "flatpickr/dist/flatpickr.min.css"; +The package also declares a `form-components` blade component namespace. This means that +for any component you may also use the `` syntax. For the `input` +component, you would use ``. If you choose to render the components +using this method, you can safely remove the component alias from the config. + +### Overriding Components + +If you are going to override the class definition of a component, you can certainly change the class reference in the `components` +config key, but for some components, it won't use your custom class when they're referenced by the package. The best way to override +a component's class is to re-bind it in a service provider. Here's an example of using a custom class for the `label` component in your +`AppServiceProvider`: + +```php +namespace App\Providers; + +use App\View\Components\LabelOverride; +use Illuminate\Support\ServiceProvider; +use Rawilk\FormComponents\Components\Label; + +class AppServiceProvider extends ServiceProvider +{ + public function register(): void + { + $this->app->bind(Label::class, LabelOverride::class); + } +} ``` -> {note} Be sure to include these styles **above** the styles for this package so any overrides this package uses for the dependencies gets applied correctly. +This will ensure that anytime the `Label` component is resolved, it will actually use your custom `LabelOverride` class instead to render the component. More +information on this can be found in the [overriding classes](/docs/laravel-form-components/{version}/advanced-usage/overriding-classes) documentation. -### Asset URL +## Asset URL For cases where your app's root domain is not the correct path for retrieving assets, you may set a custom root path that FormComponents will use to link to its JavaScript assets. You may specify a custom root path either in the config file, @@ -175,11 +201,11 @@ In the config: In your layouts: ```html -@fcJavaScript(['asset_url' => 'myapp.com/app']) - -@fcScripts(false, ['asset_url' => 'myapp.com/app']) +@fcScripts(['asset_url' => 'myapp.com/app']) ``` +> {note} If you use the self-closing tag ``, you must define the custom URL in the config file. + ## Prefixing Using components from this library might conflict with other ones from a different @@ -200,8 +226,16 @@ return [ Now all components can be referenced as usual but with the prefix before their name: ```html - + ``` For obvious reasons, the docs don't use any prefix in their code examples. So keep this in mind when setting a prefix and copying/pasting code snippets. + +## Translations + +If you need to customize any of the language lines from the package, you may publish the translation files with this command: + +```bash +php artisan vendor:publish --tag="form-components-translations" +``` diff --git a/docs/introduction.md b/docs/introduction.md index 9fc4e0f..438d7e8 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -17,4 +17,4 @@ try one of these alternatives if your needs differ: ## Disclaimer -This package is not affiliated with, maintained, authorized, endorsed or sponsored by Laravel, TailwindCSS, Laravel Livewire, or any of its affiliates. +This package is not affiliated with, maintained, authorized, endorsed or sponsored by Laravel, TailwindCSS, Laravel Livewire, Alpine.js, or any of its affiliates. diff --git a/docs/questions-and-issues.md b/docs/questions-and-issues.md index 4af8c55..4d3ac99 100644 --- a/docs/questions-and-issues.md +++ b/docs/questions-and-issues.md @@ -4,6 +4,6 @@ sort: 5 --- Find yourself stuck using the package? Found a bug? Do you have general questions or suggestions for improving the package? -Feel free to [create an issue on Github](https://github.com/rawilk/laravel-form-components/issues) and I'll try to address it as soon as possible. +Feel free to [create an issue on GitHub](https://github.com/rawilk/laravel-form-components/issues), and I'll try to address it as soon as possible. > {note} If you've found a bug regarding security please email [randall@randallwilk.dev](mailto:randall@randallwilk.dev) instead of using the issue tracker. diff --git a/docs/requirements.md b/docs/requirements.md index 83b1192..9048c49 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -6,11 +6,15 @@ sort: 2 ## General Requirements - PHP **8.0** or greater -- Laravel **8.70** or greater -- TailwindUI for styling -- Alpine.js -- Popper.js (when using components like custom-select) +- Laravel **9.0** or greater +- TailwindCSS for styling +- [Alpine.js](https://alpinejs.dev/) **3.0** or greater +- [Alpine Focus Plugin](https://alpinejs.dev/plugins/focus) (used in the custom-select components) +- [Popper.js](https://popper.js.org/) (when using components like custom-select) - Blade Heroicons (can easily swap for other icon libraries) +- [Flatpickr](https://flatpickr.js.org/) (when using the date picker component) +- [Quill](https://quilljs.com/) (when using the quill editor component) +- [Filepond](https://pqina.nl/filepond/) (when using the filepond component) ## Version Matrix @@ -18,4 +22,6 @@ sort: 2 | ---------- | --------------- | --------------- | | 8.0 - 8.55 | 1.0.0 | 5.1.0 | | 8.56 | 6.0.0 | 6.0.2 | -| 8.70 | 7.0.0 | | +| 8.70 | 7.0.0 | 7.1.7 | +| 9.0 | 7.0.0 | | +| 10.0 | 7.1.7 | | diff --git a/docs/rich-text/quill.md b/docs/rich-text/quill.md index ec22c8d..ee7b4ff 100644 --- a/docs/rich-text/quill.md +++ b/docs/rich-text/quill.md @@ -9,10 +9,10 @@ The `quill` component provides a rich text editor. Before using this component, ## Installation -While the `quill` component works out-of-the-box when you've [set the directive](/docs/laravel-form-components/{version}/installation#directives), we recommend that you install and compile the JavaScript libraries before you deploy to production: +The `quill` component requires the following third-party libraries to work properly: -- [Alpine.js](https://github.com/alpinejs/alpine) `^3.9` -- [Quill](https://quilljs.com) `^1.3` +- Alpine.js +- Quill You may install Quill via npm: @@ -23,24 +23,28 @@ npm i quill --save You can then import it in your project using imports: ```js -import Quill from 'quill'; +import Quill from "quill"; + +window.Quill = Quill; ``` You will also need to import the theme styles you are using into your stylesheets: ```css -@import 'quill/dist/snow.css'; +@import "quill/dist/snow.css"; ``` You are of course free to use the cdn links alternatively if that's more your style: ```html - + ``` Be sure to replace `1.0.0` with the version you are planning on using. +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage The most basic usage of the `quill` component involves just adding a self-closing tag: @@ -49,7 +53,8 @@ The most basic usage of the `quill` component involves just adding a self-closin ``` -This will create a new quill editor inside of a content editable div. +This will create a new quill editor inside of a content editable div. If a `name` attribute is provided, we will render a hidden input for regular +form submissions, which will keep its value in sync with the value of the quill editor. ## Livewire Integration @@ -63,20 +68,22 @@ The `quill` component integrates easily with livewire out-of-the-box and just re ## X-Model Usage -You may use `x-model` on the component as well, however there is one caveat to it. You will need to listen for a `quill-input` event on your alpine component and update your -model accordingly. We dispatch that custom event instead of `input` because the quill editor also dispatches the input event, but it doesn't give you the actual value -of the input. With the custom event, you can more reliably update your alpine models. +You may use `x-model` on the component as well. ```html -
    +
    ``` +You may also use modifiers to x-model, such as `debounce`. + ## Options -The `quill` component accepts most of the options that the quill editor provides, however some options will require you to provide a `Rawilk\LaravelFormComponents\Dto\QuillOptions` object to set them. + +The `quill` component accepts most of the options that the quill editor provides, however some options will require you to provide a `\Rawilk\LaravelFormComponents\Dto\QuillOptions` object to set them. ### Readonly + To make the editor readonly, you may pass in a truthy value to the component: ```html @@ -84,6 +91,7 @@ To make the editor readonly, you may pass in a truthy value to the component: ``` ### Placeholder + Like most other inputs, you may use a placeholder to show when there is no value set: ```html @@ -91,6 +99,7 @@ Like most other inputs, you may use a placeholder to show when there is no value ``` ### QuillOptions + For all other options, you should pass in an instance of the `QuillOptions` object: ```html @@ -99,44 +108,89 @@ For all other options, you should pass in an instance of the `QuillOptions` obje The `QuillOptions` object is mostly useful for customizing the toolbar of the editor. +You may set some default options in a service provider. For example, if you always want to hide the bold toolbar button, you may do +so like this in your AppServiceProvider: + +```php +namespace App\Providers; + +use Illuminate\Support\ServiceProvider; +use Rawilk\FormComponents\Dto\QuillOptions; + +class AppServiceProvider extends ServiceProvider +{ + public function boot(): void + { + QuillOptions::defaults(function () { + return (new QuillOptions)->hideBold(); + }); + } +} +``` + ### Custom Toolbar + By default, most of the buttons available to quill will be rendered onto the editor. Using the `QuillOptions` object, you may specify which buttons should be hidden and also provide custom buttons as well. ```html - + ``` -The above example will hide the bold and ordered list buttons from the editor. For a full list of available methods, you can refer to the source class: https://github.com/rawilk/laravel-form-components/blob/main/src/Dto/QuillOptions.php +The above example will hide the bold and ordered list buttons from the editor. For a full list of available methods, you can refer to the source class: https://github.com/rawilk/laravel-form-components/blob/{branch}/src/Dto/QuillOptions.php You may alternatively pass in your own toolbar if you need to: ```html -toolbar([ ['bold', 'italic'], [['list' => 'ordered'], ['list' => 'bullet']], -])" /> +])" +/> ``` In this example, only buttons for bold, italic, and ordered/unordered lists will appear in the toolbar. ### Custom Toolbar Button + If you need a custom toolbar button/dropdown list, you may provide one with the `withToolbarButton` method on `QuillOptions`. You will need to provide -a key (id) for the button, a JavaScript handler, and optionally an array of options if it is a dropdown button. Your handler will automatically be converted from -a string to a JavaScript function by the quill component JS, and will be provided a `value` variable from the quill editor. +a key (id) for the button and optionally an array of options if it is a dropdown button. + +```html + +``` + +You will then need to utilize the `config` slot on the component to define a JavaScript handler for the toolbar button: ```html - + + + toolbarHandlers: { variables: function (value) { value = `[[ ${value} + ]]`; const quill = instance.__quill; const cursorPosition = + quill.getSelection().index; quill.insertText(cursorPosition, value); + quill.setSelection(cursorPosition + value.length); }, }, + + ``` This example will provide a custom dropdown menu with two options, and when each one is clicked on, it will insert the text of the option into the editor at the current cursor position of the user. Your work is not done yet, however. Quill editor uses CSS styling to render the text into the toolbar buttons, so you will need to add some styles to your stylesheet: ```css .ql-picker.ql-variables .ql-picker-label:before { - content: 'Variables'; + content: "Variables"; } .ql-picker.ql-variables .ql-picker-item[data-value]:before { @@ -149,3 +203,96 @@ This example will provide a custom dropdown menu with two options, and when each ``` > {tip} Quill creates a css class on your button depending on the key you provide it. You will need to change `.ql-variables` to whatever key name you provide it. + +## Config Slot + +If you need to define JavaScript handlers for a [custom toolbar button](#user-content-custom-toolbar-button), you may use the `config` +slot to do this. The config slot is inside a JavaScript function that returns an object and has access to the following variables: + +| variable | description | +| `instance` | The Alpine data instance for the quill component. To access to the quill editor instance, you can do so via `instance.__quill` | +| `quillOptions` | An object containing the options generated by the component | + +For a complete list of quill configuration options, see [Quill Configuration](https://quilljs.com/docs/configuration/). + +## onInit Slot + +If you need to define your own JavaScript callbacks for Quill, you may use the `onInit` slot. This slot is rendered inside a JavaScript +function that has access to an `instance` variable, which provides you access to the Alpine data object for the `quill` component. If you need +access to the quill editor instance, you can do so via `instance.__quill`. + +Here's an example of how you could hook into the `selection-change` event that Quill fires: + +```html + + + instance.__quill.on('selection-change', function (range, oldRange, + source) { // do something }); + + +``` + +> {note} If you need to hook into the `text-change` event fired by Quill, you should use the [onTextChange](#user-content-onTextChange-slot) slot instead. + +## onTextChange Slot + +Whenever the text content of the quill editor is changed, Quill will fire a `text-change` event that can be listened for. Since our component's JavaScript +already listens for that event, we've provided a slot that can be used to perform additional actions if needed. The slot is rendered inside a function +that has access to an `instance variable`, which provides you access to the Alpine data object for the `quill` component. If you need access to the quill +editor instance, you can do so via `instance.__quill`. + +```html + + + let value = instance.__quill.root.innerHTML; console.log(value); + + +``` + +If you want to prevent our component from updating the value, or dispatching an `input` event, you may return `false` from the slot: + +```html + return false; +``` + +## API Reference + +### props + +| prop | description | +| -------------- | ----------------------------------------------------------------------------------------- | +| `name` | Name of the input | +| `id` | Id of the input. Defaults to `name`. | +| `value` | The initial value for the input | +| `showErrors` | If a validation error is present for the input, it will show the error state on the input | +| `autoFocus` | Give focus to the input on page load | +| `readonly` | Makes the editor readonly | +| `placeholder` | Sets a placeholder text in the editor | +| `quillOptions` | The `QuillOptions` configuration object | + +### slots + +| slot | description | +| -------------- | ----------------------------------------------------------- | +| `config` | Set JavaScript configuration options and toolbar handlers | +| `onTextChange` | Hook into the `text-change` event fired by Quill | +| `onInit` | Place to define custom JavaScript event listeners for Quill | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the quill element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'quill' => [ + // Automatically focus the editor on page load by default. + 'auto_focus' => false, + ], +], +``` diff --git a/docs/selects/custom-select.md b/docs/selects/custom-select.md index c563c7f..f81e1d4 100644 --- a/docs/selects/custom-select.md +++ b/docs/selects/custom-select.md @@ -5,20 +5,23 @@ sort: 2 ## Introduction -Heavily based on [Tailwind UI's custom selects](https://tailwindui.com/components/application-ui/forms/select-menus), the `custom-select` component provides a nice alternative -to the native select menu. Using this menu will provide your select menus with search functionalities and -custom option markup while still providing usability functionalities such as keyboard navigation. +The `custom-select` component provides a nice alternative to the native select menu. Using this component will provide your select +menus with search functionalities and custom option markup while still providing usability functionalities such as keyboard navigation. + +If you provide a `name` for the select, the component will automatically render hidden inputs for the selected value(s). + +As of v8, this component is heavily based on the [Listbox](https://alpinejs.dev/component/headless-listbox/) component from Alpine UI Components, +but I've put my own spin on it and added some extra functionality to it. ## Installation -The custom select component requires Alpine.js and Popper.js, as well as some custom JavaScript written into the package to work. -Ensure you have the proper [directives](/docs/laravel-form-components/installation#directives) in your layout file. -In production, we recommend you install and compile the JavaScript libraries before you deploy: +The following third-party libraries are required for `custom-select` to work properly: -- [Alpine.js](https://github.com/alpinejs/alpine) `^3.8` -- [Popper.js](https://popper.js.org/) `^2.9.1` +- Alpine.js +- Alpine [Focus Plugin](https://alpinejs.dev/plugins/focus) +- Popper -> {tip} See the [JavaScript Dependencies section](/docs/laravel-form-components/{version}/installation#javascript-dependencies) for more information on installing them. +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. ## Basic Usage @@ -28,10 +31,10 @@ You can use the select menu by providing some basic options. ``` -This will output a custom select menu with options for `foo` and `bar`. The menu is toggled open and closed by using a `
    ` element with a `role="button"` attribute, -and renders each option in an `
  • ` tag inside of a `
      `. We have done our best to include all of the necessary aria attributes for -accessiblity, but we are by no means accessibility experts. If you notice any accessibility issues, please submit a PR to the github -repository to fix them. +This will output a custom select menu with options for `foo` and `bar`. The menu is toggled open and closed by a button that displays +the current selection, and each option is rendered in an `
    • ` tag inside a `
        `. We have done our best to include all the necessary +aria attributes for accessibility, but we are by no means accessibility experts. If you notice any accessibility issues, please submit a +PR to the GitHub repository to fix them. ## Options @@ -40,10 +43,12 @@ If you provide an array of strings, the component will use the strings as both t should provide an array of keyed arrays for each option, or you can even pass in an array of Eloquent models as options. ```html - 'foo', 'name' => 'Foo'], ['id' => 'bar', 'name' => 'Bar'], -]" /> +]" +/> @@ -57,30 +62,31 @@ of the option via `value-field` and `label-field`. ### Customizing the option display -If you want more control over the display of an option, you can render your options manually in a `@foreach` loop and use the -`` component to render each option. +We have provided a slot called `optionTemplate` to customize how each option is rendered in the menu, however you'll need to use JavaScript +to customize it since the `` component is rendered recursively when there are opt groups present. +The content of each option is wrapped in an `x-data` directive that contains a variable called `option` containing all the properties +present on the option. + +Assuming you have a property called "foo" on the option, we'll render that property out in a span tag and make the text italic: ```html - - @foreach ($options as $option) - - {{ $option->name }} - - @endforeach + + + + ``` -> {note} It is important to still pass in the `label` prop to each option as our JavaScript will use that to determine the -> text to display for the selected option. - +> {tip} This slot will apply to "opt group" options as well, so you may need to check if it's an opt group option in your template. See [$customSelectOption](#user-content-$customSelectOption) + ### Customizing the selected option display -By default, when an option is selected it will display the same text that is provided to it on the `label` prop on the select's trigger. -If you want to display something different for the selected option, you may provide a value to the `selected-label` prop on the option. -This is also possible when not using the options slot on the select by specifying the `selected-label-field` prop on the custom select. +By default, when an option is selected it will display the same text that is provided to it on the `label` prop on the custom-select's trigger. +If you want to display something different for the selected option, you may provide a value to the `selected-label-field` attribute on the select. +If nothing is provided, it will default to the `label-field` attribute. ```html - + + +``` + +If you are using a multi-select, the selected template slot will be slightly different, since it will be in an Alpine `x-for` loop. +In this case, you will need to use a variable exposed to you, called `selectedObject`, which behaves the same way as the example above. + +```html + + + + + +``` + ### Disabling Options You may disable specific options by setting `disabled` to true on the option: ```html - + ``` You can use a different key for `disabled` on the option, by specifying it via the `disabled-field` attribute on the select. ```html - + ``` ### Opt Groups -You can specify an option as an "optgroup" header by using a `true` value on an `is_opt_group` key on the option: +The custom-select component will automatically determine if an option is considered an "opt group" by the presence of `children` +on the option. If there is a non-empty array of children on the a `children` property on the option, the component will render +the option as an "opt group", and recursively render each of its children (1 level deep only). ```html - + ``` -> {tip} You can use a different key for the opt group by specifying it for the `is-opt-group-field` on the select. - -> {note} As of v7, you should flatten your array of options as the custom select will no longer render an opt group's options -> automatically. +> {tip} You can use a different key for children by specifying it for the `children-field` on the select. + +### Manual Rendering + +If you prefer to render options yourself, you can do so in the default slot using the `` component. The option component +will automatically be aware of the following fields from `custom-select`: + +- valueField +- labelField +- disabledField +- childrenField +- optionSelectedIcon + +Because of this, the `custom-select-option` component must be placed inside a `custom-select` component. + +The only prop you need to provide is `value`, which should be an array of an option, or a model. If there are children present on the option, +the component will automatically render them as well while making the option an "opt group". + +```html + + @foreach ($options as $option) + + @endforeach + +``` + +You can of course customize the option display using the `optionTemplate` slot on the option. This will behave exactly the same as +it does on [customizing the option display](#user-content-customizing-the-option-display) on the parent component. ## Filtering @@ -132,24 +196,31 @@ You may provide search functionality on a custom select by setting `searchable` This will provide basic search functionality, which will hide any non-matching options as the user types. -> {note} By default `searchable` is set to true on the select component. +> {tip} By default `searchable` is set to true on the select component. ## Server-Side Filtering If you use Livewire, you can easily add server-side filtering of options via the `livewire-search` prop on the component. ```html - + ``` In this example, this will require you to have a method called `handleSearch` on your livewire component. Our JavaScript will call that method via livewire's JavaScript API, passing it the value of the current search term. Your livewire component -should filter out the options based on the search. The select component debounces the search input so each keystroke is +should filter out the options based on the search. The select component debounces the search input so each keystroke is not triggering another ajax request to your server. +Your component should then re-render itself with the filtered options. + ## Multiple Select -You can easily make a select accept multiple selected options by using the `multiple` attribute. +You can easily make a select accept multiple selected options by using the `multiple` attribute. Each of the selected options +will appear on the trigger as a "token", which will allow the user to click on them to remove them. ```html @@ -171,6 +242,10 @@ In this example, the user will only be able to select a maximum of 3 options. With a multiple select, you may require the user to select a minimum amount of options. You can specify this via the `min-selected` prop. +```html + +``` + ## Optional Selects For times that you want to allow users to clear the select option(s), you can mark a custom select as `optional`. This @@ -180,57 +255,212 @@ works for both single and multi-select modes, and provides a clear button next t ``` +> {note} In a multi-select, if you have `min-selected` set to more than 1, `optional` will not apply here. + ## Positioning -As of v4, the custom-select component makes use of Popper.js for positioning the select menu. This should remove the need for fixed positioning +The custom-select component makes use of Popper.js for positioning the select menu. This should remove the need for fixed positioning the select menu now. In addition to positioning the menu when opened, Popper.js will also re-position the menu as needed when the page is scrolled. -## Component Reference - -### Props - -| Prop | Type | Default | Description | -|---------------|-----------------|--------------|--------------------------------------------------------------------------------| -| name | `string`, `null` | `null` | Name of input | -| id | `string`, `null` | `null` | ID of input. Defaults to name | -| value | `mixed` | `null` | Current/previous value of input | -| options | `array`, `Collection` | `[]` | Options to render in select | -| multiple | `boolean` | `false` | Allow multiple selected options | -| minSelected | `int` | 1 | Min. amount of options that must be selected | -| maxSelected | `null`, `int` | `null` | Max amount of options that may be selected | -| disabled | `boolean` | `false` | Disable the input | -| labelledby | `null`, `string` | `null` | Add an aria-labelled by to the input | -| searchable | `boolean` | `true` | Make select searchable | -| closeOnSelect | `boolean` | `false` | Close the select when an option is selected | -| autofocus | `boolean` | `false` | Give focus to input on page load | -| optional | `boolean` | `false` | Allow value to be cleared | -| clearIcon | `null`, `string` | heroicon-o-x | Icon component name to use - see config | -| placeholder | `bool`, `null`, `string` | See lang file | Text to use when no value is selected. Use `false` for no placeholder | -| noOptionsText | `bool`, `null`, `string` | See lang file | Text to use when no options are available. Use `false` for none | -| noResultsText | `bool`, `null`, `string` | See lang file | Text to use when no options are available from searching. Use `false` for none | -| showCheckbox | `null`, `bool` | `null` | Show a checkbox/radio next to each option. Defaults to `true` on multi select and `false` on single select | -| valueField | `string` | `id` | Key to use for the option's value | -| labelField | `string` | `name` | Key to use for the option's label | -| selectedLabelField | `string`, `null` | `null` | Key to use for the options' label when selected. Defaults to labelField | -| disabledField | `string` | `disabled` | Key to use to determine if an option is disabled | -| isOptGroupField | `string` | `is_opt_group` | Key to use to determine if an option is an opt group | -| extraAttributes | `string`, `HtmlString` | `''` | Extra attributes to render on the component | -| showErrors | `boolean` | `true` | Show validation error state | -| livewire | `boolean` | `false` | If `true`, provides livewire instance to component JavaScript. Will be true if a `wire:model` is provided | -| livewireSearch | `null`, `string` | `null` | Name of livewire component search method to call | - -### Events +If absolute positioning is breaking your layout, you can force Popper to use fixed positioning, however you may need to style the width of the menu manually. +All you need to do is passed a `fixed` attribute to the component. -These are the events that our JavaScript will emit. +```html + +``` -| Event | Args | Description | -| --- |-----------|-------------------------------| -| input | `newValue` | Emitted when value is updated | +## Orientation -### Listeners +Normally the custom select component will orient itself vertically. If you want to have it orient itself horizontally, set the `horizontal` attribute. -These are JavaScript event listeners our component listens for that you can broadcast to it. +```html + +``` + +## Autofocus + +If you want to give focus to the select on page load, you can set the `autofocus` attribute. + +```html + +``` + +## Addons + +The custom select component supports most of the available addons this package offers. Header over to the [Addons](/docs/laravel-form-components/{version}/advanced-usage/addons) documentation +for an in-depth guide on how to use them. + +> {note} The custom-select component does not support the `trailingInlineAddon` or the `trailingIcon` addons. + +## Keyboard Shortcuts + +| key | description | +| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[Enter/Space]` | Open the select when it's closed or select the focused option when the select is open. Will not select an option if select is set to `searchable` and the search input is focused | +| `[Escape]` | Close the select | +| `[Arrow Keys]` | Focuses the next/previous non-disabled option | +| `[Home/PageUp]` | Focuses the first non-disabled option | +| `[End/PageDown]` | Focuses the last non-disabled option | +| `[A-z]` | Focuses the first option matching the keyboard input. Only triggers when select is not set to `searchable`, or the search input is not focused | +| `[Backspace]` | In a multi-select, when the menu is closed and there are selected options, it will de-select the last selected option | + +## API Reference + +### props + +| prop | description | +| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Name of the select | +| `id` | Id of the select. Defaults to `name`. | +| `value` | Value of the select. Gets ignored if `wire:model` or `x-model` is present | +| `showErrors` | If a validation error is present for the select, it will show the error state on the select | +| `multiple` | Allow multiple options to be selected | +| `options` | An array or Collection of options to be rendered | +| `size` | Define a size for the select. Default size is `md` | +| `valueField` | Property on an option to use for the value | +| `labelField` | Property on an option to use for the text | +| `selectedLabelField` | Property on an option to use in the select trigger for display. Defaults to `labelField` | +| `disabledField` | Property on an option to use to determine if it is disabled | +| `childrenField` | Property on an option to determine if it has children. Will render as an "opt group" option if children is present and not empty | +| `minSelected` | A minimum amount of options that must be selected in a multi-select | +| `maxSelected` | A maximum amount of options that may be selected in a multi-select | +| `optional` | A boolean value indicating the user may clear the selected value(s). | +| `buttonIcon` | A name of an icon component to use for the arrows on the right of the trigger | +| `searchable` | A boolean value indicating that a search box should be rendered in the menu | +| `livewireSearch` | A name of a Livewire component method to handle a server-side search | +| `clearable` | Allows a clear button to show on the select trigger. Will not show if `optional` is set to `false` | +| `clearIcon` | A name of an icon component to render in the clear button | +| `optionSelectedIcon` | A name of an icon component to render next to an option in the menu when it is selected | +| `placeholder` | Placeholder text to show in the trigger when no option is selected. | +| `noResultsText` | Text to display in the menu when a search term is present, but no matching options found | +| `noOptionsText` | Text to display in the menu when no options are found and no search term is present | +| `alwaysOpen` | A boolean value indicating that the menu should always be open | +| `containerClass` | A CSS class to apply to the container of the select menu | +| `extraAttributes` | Pass an array of HTML attributes to render on the select | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | + +### slots + +| slot | description | +| ------------------ | --------------------------------------------------- | +| `selectedTemplate` | Customize how the selected option is displayed | +| `optionTemplate` | Customize how each option is displayed in the menu | +| `before` | Render HTML before the select and/or leading addons | +| `after` | Render HTML after the select and/or trailing addons | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the custom-select element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + + // Set the fields to use by default for properties on options in select components. + 'value_field' => 'id', + 'label_field' => 'name', + // Will default to label field if null - only applies to custom selects + 'selected_label_field' => null, + 'disabled_field' => 'disabled', + 'children_field' => 'children', + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios. + 'size' => 'md', + ], + + 'custom_select' => [ + // Apply a CSS class by default to the root element of the custom select. + // Note: this will also apply to tree-select as well. + 'container_class' => null, + + // Apply a CSS class by default to the custom select button. + 'input_class' => null, + + // Apply a CSS class by default to the custom select menu. + 'menu_class' => null, + + // Make custom selects searchable by default. + 'searchable' => true, + + // Make custom selects clearable by default. + // Will not show the clear button if the select is not optional. + 'clearable' => true, + + // Make custom selects optional by default. When marked as optional, custom select + // will allow you to clear out its value, unless it has a minimum amount of options + // required in a multi-select. + 'optional' => false, + + // Set the default icon to use to show that an option is selected. + // Set to null to disable it. + 'option_selected_icon' => 'heroicon-m-check', + + // Define the name of the icon to show on the custom select button by default. + // Set to null to hide it. + 'button_icon' => 'heroicon-m-chevron-down', + + // Define the default clear icon that will show on the custom select button and + // multi-select selected options. Set to null to hide it. + 'clear_icon' => 'heroicon-m-x-mark', + + // In a multi-select, this is the minimum amount of options that must be selected. + // Set to null or 0 to disable it. + 'min_selected' => null, + + // In a multi-select, this is the maximum amount of options that can be selected. + // Set to null to disable it. + 'max_selected' => null, + ], +], +``` + +### events + +These are the events that our JavaScript will emit. + +| Event | Args | Description | +| ----- | ---------- | ----------------------------- | +| input | `newValue` | Emitted when value is updated | -| Listener | Args | Description | -| --- | --- |--------------------------------------------------------------------------------------| -| :name-value-manually-updated | `newValue` | Update the current value. Replace `:name` with a slugified version of the input name | +### $customSelect + +A magic variable that exposes information about the current state of the select menu (element containing `x-data="customSelect(...)`) + +| property | description | +| -------------------- | --------------------------------------------------------------------------------------------- | +| `isOpen` | Select menu is open or not | +| `isDisabled` | Select menu is disabled or not | +| `isSearchable` | Select menu is searchable or not | +| `selected` | Currently selected raw value | +| `active` | Currently active (highlighted) option | +| `selectedObject` | Object representation of the selected value. Will be an array of objects in multi-select mode | +| `hasValue` | Whether or not select has a selected option | +| `shouldShowClear` | Are conditions right to show the clear button | +| `canSelectMore` | Can more options be selected in a multi-select | +| `canDeselectOptions` | Can an option(s) be de-selected | +| `hasOptions` | Does the menu have any registered options | +| `hasSearch` | Is there a current search query | + +### $customSelectOption + +A magic variable that exposes information about the current state of an option (element containing `x-custom-select:option`) + +| property | description | +| ------------ | -------------------------------------------------------------------------------------------- | +| `isActive` | A boolean used to determine whether or not an option is currently active (hovered over) | +| `isSelected` | A boolean used to determine whether or not an option is currently selected | +| `isDisabled` | A boolean used to determine whether or not an option is currently disabled | +| `isOptGroup` | A boolean used to determine if an option is considered an "opt group" (has children options) | diff --git a/docs/selects/select.md b/docs/selects/select.md index c847abd..19ae0f1 100644 --- a/docs/selects/select.md +++ b/docs/selects/select.md @@ -6,7 +6,7 @@ sort: 1 ## Introduction The `select` component offers an easy way to provide select menus in your forms. -By simply setting the `name` attribute it also automatically defines your `id` +By simply setting the `name` attribute it also automatically defines your `id` and makes sure old values are respected. ## Basic Usage @@ -35,17 +35,56 @@ key/value pairs. This will allow the select component to automatically determine ``` +You can also provide more complex arrays for the options too. + +```html + + +``` + +This will set each option's value to the `id`, and the text of the option to the `name`. You can of course customize these fields for each select with the +`valueField` and `labelField` attributes: + +```html + + +``` + +You are also able to pass in an array of Eloquent Models to the select as well: + +```html + +``` + ### Via Default Slot -Another way is to use the default slot on the component: +Another way to provide options is to use the default slot on the component: + ```html - - + + ``` -> {note} When using the default slot, the select component will not be able to determine if the options in the slot are selected or not automatically for you. +> {note} When using the default slot, the select component will not be able to determine if the options in the slot are selected or not automatically for you. You may +> use the `isSelected` method on the component though for convenience. ### Via The Append Slot @@ -54,14 +93,15 @@ add your slotted options **after** the passed in options: ```html - + - + ``` ### Combining Methods + You can also pass in options using multiple methods. For example, if you pass options in using the `options` attribute, and also via the default slot, your slotted options will be rendered **before** the passed in options: @@ -77,10 +117,98 @@ attribute, and also via the default slot, your slotted options will be rendered You can easily create a multiple select by setting `multiple` to `true`: ```html - + ``` -## Reference - -Since the select component extends the [input component](/docs/laravel-form-components/{version}/inputs/input), you are able -to do a lot of the same things you can with the input element, such as error handling and addons. +## Opt Groups + +The select component can automatically render options as an `` for you without you needing to manually +render the options yourself. The component will check for a `children` property on the option (name of property is configurable). +If it is present, and is not an empty array, the component will render the parent option as an ``, and then loop through +each of the children and render them as normal options. + +> {note} The children options should have the same property structure as the parent option does. + +## Addons + +The select component supports most of the available addons this package offers. Header over to the [Addons](/docs/laravel-form-components/{version}/advanced-usage/addons) documentation +for an in-depth guide on how to use them. + +## API Reference + +### props + +| prop | description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `name` | Name of the select | +| `id` | Id of the select. Defaults to `name`. | +| `value` | Value of the select. Gets omitted if `wire:model` or `x-model` is present | +| `containerClass` | Defines a CSS class to apply to the **container** of the select | +| `size` | Define a size for the select. Default size is `md` | +| `showErrors` | If a validation error is present for the select, it will show the error state on the input | +| `extraAttributes` | Pass an array of HTML attributes to render on the select | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the input on the select | +| `trailingAddon` | Render text on the right of the select | +| `trailingInlineAddon` | Render text inside the input on the select | +| `trailingIcon` | Render an icon on the right of the select | +| `multiple` | Allow muti-select mode | +| `options` | An array or Collection of options to render | +| `valueField` | Property on an option to use for the value | +| `labelField` | Property on an option to use for the text | +| `disabledField` | Property on an option to use to determine if it is disabled | +| `childrenField` | Property on an option to determine if it has children. Will render as an `` if children is present and not empty | + +### slots + +| slot | description | +| --------------------- | --------------------------------------------------------- | +| `append` | Render options after passed in options have been rendered | +| `before` | Render HTML before the select and/or leading addons | +| `after` | Render HTML after the select and/or trailing addons | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | +| `trailingInlineAddon` | Render text inside the select on the right | +| `trailingIcon` | Render an icon on the right of the select | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the select element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + + // Set the fields to use by default for properties on options in select components. + 'value_field' => 'id', + 'label_field' => 'name', + 'disabled_field' => 'disabled', + 'children_field' => 'children', + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios and custom select. + 'size' => 'md', + + // Classes applied by default to input parent div. + // Will also apply to select. + 'container_class' => null, + ], + + 'select' => [ + // Automatically apply a CSS class to each select. + 'input_class' => null, + ], +], +``` diff --git a/docs/selects/timezone-select.md b/docs/selects/timezone-select.md index 94a2360..28bd272 100644 --- a/docs/selects/timezone-select.md +++ b/docs/selects/timezone-select.md @@ -5,10 +5,20 @@ sort: 3 ## Introduction -Laravel form components provides a simple way to render a select with timezones. This kind of input can be useful when you need to allow users +Form Components for Laravel provides a simple way to render a select with timezones. This kind of input can be useful when you need to allow users to choose what timezone they are in. The timezone select extends the regular select component, so anything you can do with the normal select can be done with the timezone select. +## Installation + +If you choose to render the timezone select as a `custom-select`, the following third-party libraries will need to be installed: + +- Alpine.js +- Alpine [Focus Plugin](https://alpinejs.dev/plugins/focus) +- Popper + +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. + ## Basic Usage The most basic usage of the timezone select involves setting a name attribute: @@ -26,10 +36,14 @@ Via config: ```php ... -'timezone_subset' => [\Rawilk\FormComponents\Support\TimeZoneRegion::AMERICA], +'timezone_subset' => [\Rawilk\FormComponents\Support\TimeZoneRegionEnum::America->value], ``` +> {note} If you are using php 8.0, you'll need to use the `\Rawilk\FormComponents\Support\TimeZoneRegion` class instead. Note that this +> class is deprecated and will be removed in future versions if php 8.0 support is dropped. + Via prop: + ```html ``` @@ -38,16 +52,138 @@ With both methods, you can use a boolean value `false` to include every timezone ## Custom Select Support -As of version `1.4.0`, the timezone select can be rendered either as a native select input, or by using the -[custom-select component](/docs/laravel-form-components/components/custom-select). To use the custom-select +The timezone select can be rendered either as a native select input, or by using the +[custom-select component](/docs/laravel-form-components/{version}/selects/custom-select). To use the custom-select component, simply pass in a true boolean value for the `use-custom-select` attribute on the timezone select. ```html ``` -By default, the timezone select uses the native select input, so you will explicitly tell it to use -the custom-select component any time you render the timezone select component. +By default, the timezone select is configured to use the `custom-select` component, so you'll need to make sure you have +the required third-party assets [installed](#user-content-installation). + +## Addons + +The timezone select component supports most of the available addons this package offers. Header over to the [Addons](/docs/laravel-form-components/{version}/advanced-usage/addons) documentation +for an in-depth guide on how to use them. + +## API Reference + +### props + +| prop | description | +| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Name of the select | +| `id` | Id of the select. Defaults to `name`. | +| `value` | Initial value of the select | +| `containerClass` | Defines a CSS class to apply to the **container** of the select | +| `size` | Define a size for the select. Default size is `md` | +| `showErrors` | If a validation error is present for the select, it will show the error state on the select | +| `extraAttributes` | Pass an array of HTML attributes to render on the select | +| `leadingAddon` | Render text on the left of the input | +| `leadingIcon` | Render an icon on the left of the input | +| `inlineAddon` | Render text inside the input on the left | +| `trailingAddon` | Render text on the right of the input | +| `trailingInlineAddon` | Render text inside the input on the right | +| `trailingIcon` | Render an icon on the right of the input | +| `multiple` | A boolean indicating that multiple timezones can be selected | +| `only` | Specify a subset of timezones to render. Set to `false` for all. Can be a string, or array of strings containing timezone region names. | + +Custom select only props. + +| prop | description | +| -------------------- | -------------------------------------------------------------------------------------------- | +| `useCustomSelect` | A boolean indicating whether or not to render the select using the `custom-select` component | +| `minSelected` | In a multi-select, the minimum amount of timezones that must be selected | +| `maxSelected` | In a multi-select, the maximum amount of timezones that may be selected | +| `optional` | A boolean indicating the select is optional | +| `searchable` | A boolean indicating the select is filterable | +| `clearable` | A boolean indicating the value of the select can be cleared | +| `alwaysOpen` | A boolean value indicating that the menu should always be open | +| `buttonIcon` | A name of an icon component to use for the arrows on the right of the trigger | +| `clearIcon` | A name of an icon component to render in the clear button | +| `placeholder` | Placeholder text to show in the trigger when no option is selected. | +| `optionSelectedIcon` | A name of an icon component to render next to an option in the menu when it is selected | + +### slots + +| slot | description | +| --------------------- | --------------------------------------------------- | +| `before` | Render HTML before the select and/or leading addons | +| `after` | Render HTML after the select and/or trailing addons | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | +| `trailingInlineAddon` | Render text inside the select on the right | +| `trailingIcon` | Render an icon on the right of the select | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the timezone-select element. -> {note} If you want to render it as a custom-select, you need to ensure you have followed the -[installation steps](/docs/laravel-form-components/{version}/selects/custom-select#installation) for the `custom-select` component. +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios. + 'size' => 'md', + ], + + 'custom_select' => [ + // Apply a CSS class by default to the root element of the custom select. + // Note: this will also apply to tree-select as well. + 'container_class' => null, + + // Apply a CSS class by default to the custom select button. + 'input_class' => null, + + // Apply a CSS class by default to the custom select menu. + 'menu_class' => null, + + // Make custom selects searchable by default. + 'searchable' => true, + + // Make custom selects clearable by default. + // Will not show the clear button if the select is not optional. + 'clearable' => true, + + // Make custom selects optional by default. When marked as optional, custom select + // will allow you to clear out its value, unless it has a minimum amount of options + // required in a multi-select. + 'optional' => false, + + // Set the default icon to use to show that an option is selected. + // Set to null to disable it. + 'option_selected_icon' => 'heroicon-m-check', + + // Define the name of the icon to show on the custom select button by default. + // Set to null to hide it. + 'button_icon' => 'heroicon-m-chevron-down', + + // Define the default clear icon that will show on the custom select button and + // multi-select selected options. Set to null to hide it. + 'clear_icon' => 'heroicon-m-x-mark', + + // In a multi-select, this is the minimum amount of options that must be selected. + // Set to null or 0 to disable it. + 'min_selected' => null, + + // In a multi-select, this is the maximum amount of options that can be selected. + // Set to null to disable it. + 'max_selected' => null, + ], + + 'timezone_select' => [ + // Use the custom select component by default for the timezone select. + 'use_custom_select' => true, + ], +], +``` diff --git a/docs/selects/tree-select.md b/docs/selects/tree-select.md index a413065..40573aa 100644 --- a/docs/selects/tree-select.md +++ b/docs/selects/tree-select.md @@ -5,28 +5,27 @@ sort: 4 ## Introduction -Our tree select component is an extension of our [custom select](/docs/laravel-form-components/{version}/selects/custom-select) component and provides +Our `tree-select` component is an extension of our [custom select](/docs/laravel-form-components/{version}/selects/custom-select) component and provides an input that supports options with parent/child relationships. Parent options will have a chevron next to them that will allow them to be expanded to reveal any children options they have. ## Installation -Like the custom select, the tree select component requires Alpine.js and Popper.js, as well as some custom JavaScript written into the package to work. -Ensure you have the proper [directives](/docs/laravel-form-components/installation#directives) in your layout file. -In production, we recommend you install and compile the JavaScript libraries before you deploy: +The following third-party libraries are required for `tree-select` to work properly: -- [Alpine.js](https://github.com/alpinejs/alpine) `^3.8` -- [Popper.js](https://popper.js.org) `^2.9.1` +- Alpine.js +- Alpine [Focus Plugin](https://alpinejs.dev/plugins/focus) +- Popper -> {tip} See the [JavaScript Dependencies section](/docs/laravel-form-components/{version}/installation#javascript-dependencies) for more information on installing them. +See [Third-Party Assets](/docs/laravel-form-components/{version}/installation#user-content-third-party-assets) on the installation guide for further setup information. ## Basic Usage You can use the tree select menu by providing some basic options. ```html -` element with a `role="button"` attached to it. Each option is also rendered -in an `
      • ` tag inside of a `
          ` and each parent's children are rendered inside of a nested `
            ` element. +Child options are rendered in a nested `
              ` element. ## Options @@ -46,10 +44,12 @@ If you provide an array of strings, the component will use the strings as both t of keyed arrays for each option, or you can even pass in an array of Eloquent models as options. ```html - 'foo', 'name' => 'Foo'], ['id' => 'bar', 'name' => 'Bar'], -]" /> +]" +/> @@ -63,29 +63,397 @@ sometimes this won't work. To get around this, you can specify which keys the op ### Option Children The tree select will determine if an option has children via the `children` key of an option. An option's children should be either an array or collection of child options with the -same data structure as the parent option. If you need to customize the key for children, you may use the `children-key` prop. +same data structure as the parent option. If you need to customize the key for children, you may use the `children-field` attribute. ### Customizing the option display -If you want more control over the display of an option, you can render your options manually in a `@foreach` loop and use the `` component to render each option. +We have provided a slot called `optionTemplate` to customize how each option is rendered in the menu, however you'll need to use JavaScript +to customize this since the `` component is rendered recursively when parent options are present. The content of each +option is wrapped in an `x-data` directive that contains a variable called `option` containing all the properties present on the option. + +Assuming you have a property called "foo" on the option, we'll render that property out in a span tag and make the text italic: ```html - - @foreach ($options as $option) - - {{ $option->name }} - + + + + + +``` + +> {tip} You may want to apply different formatting to your parent options, which can be checked for via `$treeSelectOption.hasChildren`. See [$treeSelectOption](#user-content-$treeSelectOption) + +### Customizing the selected option display + +By default, when an option is selected it will display the same text that is provided to it on the `label` prop on the tree-select's trigger. +If you want to display something different for the selected option, you may provide a value to the `selected-label-field` attribute on the select. +If nothing is provided, it will default to the `label-field` attribute. + +```html + +``` + +In the example above, when an option is selected, the value for the option's `short_name` will be displayed on the tree-select's trigger instead +of the option's `name` field. + +We have also provided a slot called `selectedTemplate` which will allow you to further customize how you are displaying the selected option's value. You +will need to use the `selectedObject` property on our `$treeSelect` [magic property](#user-content-$treeSelect). + +```html + + + + + +``` + +If you are using a multi-select, the selected template slot will be slightly different, since it will be in an Alpine `x-for` loop. +In this case, you will need to use a variable exposed to you, called `selectedObject`, which behaves the same way as the example above. + +```html + + + + + +``` + +### Disabling Options + +You may disable specific options by setting `disabled` to true on the option: + +```html + +``` + +You can use a different key for `disabled` on the option, by specifying it via the `disabled-field` attribute on the select. + +```html + +``` + +### Manual Rendering + +If you prefer to render options yourself, you can do so in the default slot using the `` component. The option component +will automatically be aware of the following fields from `tree-select`. + +- valueField +- labelField +- disabledField +- childrenField +- optionSelectedIcon +- hasChildIcon + +Because of this, the `tree-select-option` must be placed inside a `tree-select` component. + +The only prop you need to provide is `value`, which should be an array of an option, or a model. If there are children present on the option, +the component will recursively render and children underneath the parent option. + +```html + + @foreach ($options as $option)' + @endforeach ``` -> {note} It is important to still pass in the `label` prop to each option as our JavaScript will use that to determine the -> text to display for the selected option. +You can of course customize the option display using the `optionTemplate` slot on the option. This will behave exactly the same as +it does on [customizing the option display](#user-content-customizing-the-option-display) on the parent component. + +## Filtering + +You may provide search functionality on a tree select by setting `searchable` on the component to `true`. + +```html + +``` + +This will provide basic search functionality, which will hide any non-matching options as the user types. + +> {tip} By default `searchable` is set to true on the select component. + +## Server-Side Filtering + +If you use Livewire, you can easily add server-side filtering of options via the `livewire-search` prop on the component. + +```html + +``` + +In this example, this will require you to have a method called `handleSearch` on your livewire component. Our JavaScript will +call that method via livewire's JavaScript API, passing it the value of the current search term. Your livewire component +should filter out the options based on the search. The select component debounces the search input so each keystroke is +not triggering another ajax request to your server. + +Your component should then re-render itself with the filtered options. + +## Multiple Select + +You can easily make a select accept multiple selected options by using the `multiple` attribute. Each of the selected options +will appear on the trigger as a "token", which will allow the user to click on them to remove them. + +```html + +``` + +### Max selected + +With multiple selects, you may limit the number of options a user may select with the `max-selected` prop. + +```html + +``` + +In this example, the user will only be able to select a maximum of 3 options. + +> {note} The component expects an integer value, so be sure to pass an integer type as the value. + +### Min Selected + +With a multiple select, you may require the user to select a minimum amount of options. You can specify this via the `min-selected` prop. + +```html + +``` + +## Optional Selects + +For times that you want to allow users to clear the select option(s), you can mark a custom select as `optional`. This +works for both single and multi-select modes, and provides a clear button next to the selected option text. + +```html + +``` + +> {note} In a multi-select, if you have `min-selected` set to more than 1, `optional` will not apply here. + +## Positioning + +The tree-select component makes use of Popper.js for positioning the select menu. This should remove the need for fixed positioning +the select menu now. In addition to positioning the menu when opened, Popper.js will also re-position the menu as needed when the page is scrolled. + +If absolute positioning is breaking your layout, you can force Popper to use fixed positioning, however you may need to style the width of the menu manually. +All you need to do is passed a `fixed` attribute to the component. + +```html + +``` + +## Orientation + +Normally the tree select component will orient itself vertically. If you want to have it orient itself horizontally, set the `horizontal` attribute. + +```html + +``` + +## Autofocus + +If you want to give focus to the select on page load, you can set the `autofocus` attribute. + +```html + +``` + +## Addons + +The tree select component supports most of the available addons this package offers. Header over to the [Addons](/docs/laravel-form-components/{version}/advanced-usage/addons) documentation +for an in-depth guide on how to use them. + +> {note} The tree-select component does not support the `trailingInlineAddon` or the `trailingIcon` addons. + +## Keyboard Shortcuts + +| key | description | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `[Enter/Space]` | Open the select when it's closed or select the focused option when the select is open. Will not select an option if select is set to `searchable` and the search input is focused | +| `[Escape]` | Close the select | +| `[Arrow Keys]` | Focuses the next/previous non-disabled option | +| `[Right Arrow Key]` | Expand children options on an active option | +| `[Left Arrow Key]` | Collapse children options on an active option | +| `[Home/PageUp]` | Focuses the first non-disabled option | +| `[End/PageDown]` | Focuses the last non-disabled option | +| `[A-z]` | Focuses the first option matching the keyboard input. Only triggers when select is not set to `searchable`, or the search input is not focused | +| `[Backspace]` | In a multi-select, when the menu is closed and there are selected options, it will de-select the last selected option | + +## API Reference + +### props + +| prop | description | +| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Name of the select | +| `id` | Id of the select. Defaults to `name`. | +| `value` | Value of the select. Gets ignored if `wire:model` or `x-model` is present | +| `showErrors` | If a validation error is present for the select, it will show the error state on the select | +| `multiple` | Allow multiple options to be selected | +| `options` | An array or Collection of options to be rendered | +| `size` | Define a size for the select. Default size is `md` | +| `valueField` | Property on an option to use for the value | +| `labelField` | Property on an option to use for the text | +| `selectedLabelField` | Property on an option to use in the select trigger for display. Defaults to `labelField` | +| `disabledField` | Property on an option to use to determine if it is disabled | +| `childrenField` | Property on an option to determine if it has children. Will render as an "opt group" option if children is present and not empty | +| `minSelected` | A minimum amount of options that must be selected in a multi-select | +| `maxSelected` | A maximum amount of options that may be selected in a multi-select | +| `optional` | A boolean value indicating the user may clear the selected value(s). | +| `buttonIcon` | A name of an icon component to use for the arrows on the right of the trigger | +| `searchable` | A boolean value indicating that a search box should be rendered in the menu | +| `livewireSearch` | A name of a Livewire component method to handle a server-side search | +| `clearable` | Allows a clear button to show on the select trigger. Will not show if `optional` is set to `false` | +| `clearIcon` | A name of an icon component to render in the clear button | +| `optionSelectedIcon` | A name of an icon component to render next to an option in the menu when it is selected | +| `placeholder` | Placeholder text to show in the trigger when no option is selected. | +| `noResultsText` | Text to display in the menu when a search term is present, but no matching options found | +| `noOptionsText` | Text to display in the menu when no options are found and no search term is present | +| `alwaysOpen` | A boolean value indicating that the menu should always be open | +| `containerClass` | A CSS class to apply to the container of the select menu | +| `extraAttributes` | Pass an array of HTML attributes to render on the select | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | +| `hasChildIcon` | A name of an icon component to render next to a parent option indicating it has child options | + +### slots + +| slot | description | +| ------------------ | --------------------------------------------------- | +| `selectedTemplate` | Customize how the selected option is displayed | +| `optionTemplate` | Customize how each option is displayed in the menu | +| `before` | Render HTML before the select and/or leading addons | +| `after` | Render HTML after the select and/or trailing addons | +| `leadingAddon` | Render text on the left of the select | +| `leadingIcon` | Render an icon on the left of the select | +| `inlineAddon` | Render text inside the select on the left | +| `trailingAddon` | Render text on the right of the select | + +### config + +The following configuration keys and values can be adjusted for common default behavior +you may want for the tree-select element. + +```php +'defaults' => [ + 'global' => [ + // Show error states by default. + 'show_errors' => true, + + // Set the fields to use by default for properties on options in select components. + 'value_field' => 'id', + 'label_field' => 'name', + // Will default to label field if null - only applies to custom selects + 'selected_label_field' => null, + 'disabled_field' => 'disabled', + 'children_field' => 'children', + ], + + 'input' => [ + // Supported: 'sm', 'md', 'lg' + // Applies to all input types except for checkbox/radios. + 'size' => 'md', + ], + + 'custom_select' => [ + // Apply a CSS class by default to the root element of the custom select. + // Note: this will also apply to tree-select as well. + 'container_class' => null, + + // Apply a CSS class by default to the custom select button. + 'input_class' => null, + + // Apply a CSS class by default to the custom select menu. + 'menu_class' => null, + + // Make custom selects searchable by default. + 'searchable' => true, + + // Make custom selects clearable by default. + // Will not show the clear button if the select is not optional. + 'clearable' => true, + + // Make custom selects optional by default. When marked as optional, custom select + // will allow you to clear out its value, unless it has a minimum amount of options + // required in a multi-select. + 'optional' => false, + + // Set the default icon to use to show that an option is selected. + // Set to null to disable it. + 'option_selected_icon' => 'heroicon-m-check', + + // Define the name of the icon to show on the custom select button by default. + // Set to null to hide it. + 'button_icon' => 'heroicon-m-chevron-down', + + // Define the default clear icon that will show on the custom select button and + // multi-select selected options. Set to null to hide it. + 'clear_icon' => 'heroicon-m-x-mark', + + // In a multi-select, this is the minimum amount of options that must be selected. + // Set to null or 0 to disable it. + 'min_selected' => null, + + // In a multi-select, this is the maximum amount of options that can be selected. + // Set to null to disable it. + 'max_selected' => null, + ], + + 'tree_select' => [ + // Set the default icon to use to show that an option has children. + // Icon will be rotated to indicate when the option is expanded. + 'has_child_icon' => 'heroicon-m-chevron-right', + ], +], +``` + +### events + +These are the events that our JavaScript will emit. + +| Event | Args | Description | +| ----- | ---------- | ----------------------------- | +| input | `newValue` | Emitted when value is updated | + +### $treeSelect + +A magic variable that exposes information about the current state of the select menu (element containing `x-data="treeSelect(...)`) + +| property | description | +| ---------------------- | --------------------------------------------------------------------------------------------- | +| `isOpen` | Select menu is open or not | +| `isDisabled` | Select menu is disabled or not | +| `isSearchable` | Select menu is searchable or not | +| `selected` | Currently selected raw value | +| `active` | Currently active (highlighted) option | +| `selectedObject` | Object representation of the selected value. Will be an array of objects in multi-select mode | +| `hasValue` | Whether or not select has a selected option | +| `shouldShowClear` | Are conditions right to show the clear button | +| `canSelectMore` | Can more options be selected in a multi-select | +| `canDeselectOptions` | Can an option(s) be de-selected | +| `hasOptions` | Does the menu have any registered options | +| `hasSearch` | Is there a current search query | +| `hasExpandableOptions` | Are there any parent options registered | -> {note} The options slot will only apply to the parent options. Any child options will rely on the default rendering of options by the component. +### $treeSelectOption -## Reference +A magic variable that exposes information about the current state of an option (element containing `x-tree-select:option`) -Since the tree select is just an extension of our custom select component, they will function the same way for the most part. They only differ in regards to options. -The tree select can have option children but it can't have "opt groups" like the custom select can. Please visit the [custom select documentation](/docs/laravel-form-components/{version}/selects/custom-select) for more information -on how to use the component. +| property | description | +| ------------- | -------------------------------------------------------------------------------------------- | +| `isActive` | A boolean used to determine whether or not an option is currently active (hovered over) | +| `isSelected` | A boolean used to determine whether or not an option is currently selected | +| `isDisabled` | A boolean used to determine whether or not an option is currently disabled | +| `hasChildren` | A boolean used to determine whether or not the option has child options | +| `isExpanded` | A boolean used to determine whether or not the option has been expanded to show its children | diff --git a/docs/upgrade.md b/docs/upgrade.md index c6a1c92..e9cc902 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -3,6 +3,164 @@ title: Upgrade sort: 4 --- +## Upgrading from v7 to v8 + +Several breaking changes were introduced in v8. Please read the following carefully before upgrading. This list may not be fully comprehensive, so be sure to check the +[full changelog](https://github.com/rawilk/laravel-form-components/compare/v7.1.6...v8.0.0) for all changes that have been made. Feel free to PR any important changes that may be missing in this upgrade guide. + +### Laravel Version + +v8 of laravel-form-components now requires a minimum Laravel version of `9.0`. Be sure to update your project to at least that version. + +### Config + +If you have the package's config file published, be sure to update it to be compatible with the new config. Here are some notable changes to the config file in v8: + +- `components` is now just a simple key/value array of component aliases to class names. Any config to a component done here is now moved to the `defaults` key. +- `defaults` has been added to allow setting default values for common component options. Be sure to refer to the [config file](https://github.com/rawilk/laravel-form-components/blob/main/config/form-components.php) for a complete list of available defaults. +- the `assets` key has been removed, as the package will no longer load in 3rd party cdn assets anymore. Be sure to load them in yourself if you were relying on this in your project. +- the `link_vendor_cdn_assets` key has also been removed. + +### Blade Directives + +In v8, the package will no longer pull in 3rd party CDN assets for you anymore. We have removed the `@fcScripts` and `@fcStyles` directives, since they are not needed anymore. We have also +renamed the `@fcJavaScript` directive to `@fcScripts`. This directive will only load the JS that is written by the package to power some components. + +If using a directive isn't your style, you may also us the new `` self-closing tag to load in the package's JS. + +### Styling + +If you were overriding component definitions to modify their styles, you may not need to do that anymore. In v8, we have removed any Tailwind classes from the markup in the components, +and are instead using `@apply` in the package's CSS to apply the styles to custom class names. This should make it easier to override styles in your own project. Some custom class +names for components have changed as well, so if you are styling them in your own project, you will want to reference the component's markup to get the updated class names. + +We've also introduced a number of CSS variables to our stylesheets, which you can override in your own project's CSS to customize many certain aspects of the components using variables instead. +A full reference to the CSS variables can be found in the [variables.css](https://github.com/rawilk/laravel-form-components/blob/{branch}/resources/css/variables.css) file. + +### Checkbox Group + +The `form-checkbox-group` CSS class is now always applied to the checkbox group component, whether it is stacked or not. + +### Custom Select/Tree Select + +The custom select component has been re-written in v8. Here are some notable differences: + +- Customizing option display in the menu has changed. See [customizing the option display](/docs/laravel-form-components/{version}/selects/custom-select#user-content-customizing-the-option-display) for more info. +- Customizing the selected option has changed. See [customizing the selected option display](/docs/laravel-form-components/{version}/selects/custom-select#user-content-customizing-the-selected-option-display) for more info. +- `is_opt_group` has been deprecated for determining if an option is an "opt group" on custom-select. Provide a non-empty array of "children" on the option itself now. See [Opt Groups](/docs/laravel-form-components/{version}/selects/custom-select#user-content-opt-groups) for more info. +- The `name-value-manually-updated` listener has been removed, as it's not needed. +- `closeOnSelect` has been removed. The component will now automatically close on single selects, but stay open for multi-selects when selecting an option. +- If you were rendering "opt groups" for custom select, you should not flatten your array of options anymore. Custom select will now determine opt groups by the presence of `children` on an option now. + +### Switch Toggle + +The switch toggle component's markup has been simplified. It now uses a native checkbox input and a single div which relies on Tailwind's peer classes for styling. Some props, such +as `$labelPosition` have been removed. Please refer to the component's documentation for a complete rundown of how to use it in v8. + +### FilePond + +The way you define filepond callbacks has changed slightly. To define a callback now, you will want to use the `config` slot. Inside the slot, you will have access to +three JS variables: `instance`, `options`, and `pondOptions`. The `instance` variable is the Alpine data object for the component, and the `options` variable is the +options object that is passed to the component. Here's an example of how you could hook into Filepond's `oninit` callback: + +```html + oninit() { console.log('init', instance); }, +``` + +If you were registering plugins in the `plugins` slot, you will need to move that logic somewhere else, as we have removed this slot. See [Plugins](/docs/laravel-form-components/{version}/files/filepond#user-content-plugins) for more information. + +The `watch-value` attribute has been removed. Now any changes to a `wire:model` value will always be picked up by the component. + +### Quill + +Similar to the FilePond component, the way you define Quill callbacks and options has changed slightly. To define a callback now, you will want to use the `config` slot. You will have +access to the `instance` and `quillOptions` variables. `instance` is the Alpine data object for the component, and `quillOptions` is the options object that is passed to the component. +Here is an example of how you could define a handler for a custom toolbar button: + +```html + + toolbarHandlers: { variables: function(value) { const quill = + instance.__quill; const cursorPosition = quill.getSelection().index; + quill.insertText(cursorPosition, value); quill.setSelection(cursorPosition + + value.length); }, }, + +``` + +If you were listening for a `quill-input` event to be dispatched from the component, you will need to change it to `input`. If you are using `x-model` to bind the value, you may +not need that listener at all since the component has changed how it dispatches and updates values in v8. + +### QuillOptions + +A `defaults` static constructor has been added to QuillOptions, which should always be used to when defining the Quill options you are using. If you are familiar with the +Password class in Laravel, this is similar to that. The `defaults` constructor can be used in a service provider to define default options you always want to use for Quill. +Here's a quick example of how you could force the "bold" button to always be hidden in your AppServiceProvider. + +```php +public function boot() +{ + \Rawilk\FormComponents\Dto\QuillOptions::defaults([ + return (new \Rawilk\FormComponents\Dto\QuillOptions)->hideBold(); + ]); +} +``` + +Now when you go to use QuillOptions, you can just call `QuillOptions::defaults()`, and the bold toolbar button will always be hidden. + +The `withToolbarButton` signature has changed in this configuration object. The `$handler` parameter has been removed in favor of defining the handler in the `config` slot +as shown above. + +If you wanted to define a `variables` toolbar button for config example above for Quill, you would do it like this: + +```php +QuillOptions::defaults()->withToolbarButton('variables', [ + 'Option 1', + 'Option 2', +]); +``` + +Please refer to the Quill component documentation for more information on how to use this. + +### Datepicker + +If you need to define custom flatpickr callbacks, you need to use the `config` slot now. For example, if you need to define a custom callback for the `onOpen` event +that is fired by flatpickr, you would do it like this: + +```html + + onOpen: function (selectedDates, dateStr, instance) { // do something here. + }, + +``` + +See the [callbacks](/docs/laravel-form-components/{version}/inputs/date-picker#user-content-callbacks) section on date-picker for more information. + +### Form Group + +The CSS class given to a form group when it is considered inline has changed to `form-group--inline`. + +The `custom-select-label` prop has been removed. Form group will automatically give focus to custom selects now when the label is clicked on. + +### Timezone Region + +The `\Rawilk\FormComponents\Support\TimeZoneRegion` class has been deprecated in favor of the `\Rawilk\FormComponents\Support\TimeZoneRegionEnum` class. If you are running Php 8.1 or higher, +it is recommended to update your code to use the enum class instead. If you are running an older version of Php, you can continue to use the old class, but it will be removed in a future +release. + +### File Upload + +The file upload component now renders as a native file upload element instead of using a custom button. Because of this, the `label` prop as been removed since the +text of a native file input is not customizable. + +### Trailing Addons + +The `trailing-addon` prop and slot will now behave like the `leading-addon` prop on components, which will render the text inside a light gray background next to the input. +If you want to the text to be inside the input, use the `trailing-inline-addon` prop/slot instead. + +### Inline Addon Padding + +The `inline-addon-padding` and `trailing-addon-padding` props have been removed for all inputs. To customize the padding on either side of the input when an inline addon is present, +override either the `--inline-addon-pl` or `--inline-addon-pr` CSS variables instead. Refer to [Inline Addon](/docs/laravel-form-components/{version}/inputs/input#user-content-inline-addon) for more information. + ## Upgrading from v6 to v7 ### Laravel Version @@ -72,7 +230,7 @@ If you choose to import the compiled styles for this package into your own style @import "../../vendor/rawilk/laravel-form-components/resources/js/laravel-form-components-styles/dist/styles.min.css"; ``` -See [customizing css](/docs/laravel-form-components/{version}/advanced-usage/customizing-css#option-2-override-only-portions-in-your-css) for more information. +See [customizing css](/docs/laravel-form-components/{version}/advanced-usage/customizing-css#user-content-option-2-override-only-portions-in-your-css) for more information. ## Upgrading from v3 to v4 @@ -92,7 +250,7 @@ For more info on styling, please see [the Customizing CSS section](/docs/laravel Some components, such as the `custom-select` component, have a dependency on `Popper.js` now for positioning the menu. This will require you to ensure that dependency is installed in your project. If you customized the package's configuration file, you should make sure you pull in any updates to the configuration as well. -See [the custom select docs](/docs/laravel-form-components/{version}/selects/custom-select#installation) for more information. +See [the custom select docs](/docs/laravel-form-components/{version}/selects/custom-select#user-content-installation) for more information. ### Custom Select diff --git a/resources/views/components/inputs/textarea.blade.php b/resources/views/components/inputs/textarea.blade.php index 1c8dcf8..31cc3fd 100644 --- a/resources/views/components/inputs/textarea.blade.php +++ b/resources/views/components/inputs/textarea.blade.php @@ -1,20 +1,3 @@ -{{--
              --}} -{{-- @include('form-components::partials.leading-addons')--}} - -{{-- --}} - -{{-- @include('form-components::partials.trailing-addons')--}} -{{--
              --}} - {{-- we add an x-data directive to the container to ensure our resize directive is in an alpine scope so it will run --}}
              @include('form-components::partials.leading-addons') diff --git a/resources/views/partials/form-group-label.blade.php b/resources/views/partials/form-group-label.blade.php index 3f328d6..1fd4e1f 100644 --- a/resources/views/partials/form-group-label.blade.php +++ b/resources/views/partials/form-group-label.blade.php @@ -8,7 +8,6 @@ @unless ($label === false) {{ $label }} diff --git a/src/Components/Files/FileUpload.php b/src/Components/Files/FileUpload.php index cfedbdc..e2c9bf6 100644 --- a/src/Components/Files/FileUpload.php +++ b/src/Components/Files/FileUpload.php @@ -29,7 +29,6 @@ public function __construct( ?string $type = null, ?bool $showErrors = null, public ?bool $displayUploadProgress = null, - public ?string $label = null, public ?string $size = null, public ?string $containerClass = null, public ?bool $useNativeProgressBar = null, @@ -42,8 +41,6 @@ public function __construct( $this->showErrors = $showErrors ?? config('form-components.defaults.global.show_errors', true); $this->size = $size ?? config('form-components.defaults.input.size', 'md'); - $this->label = $label ?? __('form-components::messages.file_upload_label'); - $this->displayUploadProgress = $displayUploadProgress ?? config('form-components.defaults.file_upload.display_upload_progress', true); $this->useNativeProgressBar = $useNativeProgressBar ?? config('form-components.defaults.file_upload.use_native_progress_bar', false); diff --git a/src/Components/FormGroup.php b/src/Components/FormGroup.php index 9c00103..bf23d45 100644 --- a/src/Components/FormGroup.php +++ b/src/Components/FormGroup.php @@ -18,7 +18,6 @@ public function __construct( ?bool $showErrors = null, public ?string $helpText = null, public bool $isCheckboxGroup = false, - public ?string $labelId = null, public ?bool $marginBottom = null, public ?bool $border = null, public ?string $hint = null, diff --git a/src/Components/Inputs/CustomSelect.php b/src/Components/Inputs/CustomSelect.php index c15b40b..0eabd2e 100644 --- a/src/Components/Inputs/CustomSelect.php +++ b/src/Components/Inputs/CustomSelect.php @@ -4,6 +4,7 @@ namespace Rawilk\FormComponents\Components\Inputs; +use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\HtmlString; @@ -79,7 +80,7 @@ public function __construct( $this->valueField = $valueField ?? config('form-components.defaults.global.value_field', 'id'); $this->labelField = $labelField ?? config('form-components.defaults.global.label_field', 'name'); - $this->selectedLabelField = $selectedLabelField ?? config('form-components.defaults.global.selected_label_field') ?? $labelField; + $this->selectedLabelField = $selectedLabelField ?? config('form-components.defaults.global.selected_label_field') ?? $this->labelField; $this->disabledField = $disabledField ?? config('form-components.defaults.global.disabled_field', 'disabled'); $this->childrenField = $childrenField ?? config('form-components.defaults.global.children_field', 'children'); @@ -138,6 +139,14 @@ protected function normalizeOptions(array|Collection $options): Collection ]; } + // If the value is a simple value, we need to convert it to an array. + if (! is_iterable($value) && ! $value instanceof Model) { + return [ + $this->valueField => $value, + $this->labelField => $value, + ]; + } + return $value; }); } diff --git a/src/Components/Inputs/DatePicker.php b/src/Components/Inputs/DatePicker.php index fefa500..2c29fae 100644 --- a/src/Components/Inputs/DatePicker.php +++ b/src/Components/Inputs/DatePicker.php @@ -59,7 +59,7 @@ public function __construct( $this->ensureModeIsValid($mode); - $this->clickOpens = $clickOpens ?? config('form-components.defaults.date_picker.click_opens', true); + $this->clickOpens = $clickOpens ?? config('form-components.defaults.date_picker.click_opens', false); $this->allowInput = $allowInput ?? config('form-components.defaults.date_picker.allow_input', true); $this->enableTime = $enableTime ?? config('form-components.defaults.date_picker.enable_time', false); $this->format = $format ?? config('form-components.date_picker.format', null);