@datum-cloud/datum-ui 0.4.0 → 0.6.0-alpha.3e04d8c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -39
- package/dist/adapter-context-rWveHhDd.mjs +25 -0
- package/dist/alert/index.mjs +2 -3
- package/dist/{alert-BC2Mccfo.mjs → alert-BDj6od5I.mjs} +2 -4
- package/dist/app-navigation/index.mjs +4 -12
- package/dist/{app-navigation-DsCKgfPe.mjs → app-navigation-84ro28PU.mjs} +5 -8
- package/dist/autocomplete/index.mjs +2 -7
- package/dist/{autocomplete-DRB_kSVx.mjs → autocomplete-CkYJueBL.mjs} +7 -9
- package/dist/autosearch/index.mjs +195 -0
- package/dist/avatar/index.mjs +2 -4
- package/dist/{avatar-DyLq0xkt.mjs → avatar-BtKVcvO4.mjs} +2 -4
- package/dist/avatar-stack/index.mjs +2 -6
- package/dist/{avatar-stack-BT0dBswq.mjs → avatar-stack-oVr8tsU7.mjs} +4 -6
- package/dist/badge/index.mjs +2 -3
- package/dist/{badge-BgFj4Nsc.mjs → badge-DJR33ftJ.mjs} +2 -4
- package/dist/breadcrumb/index.mjs +2 -4
- package/dist/{breadcrumb-CJNaYyk1.mjs → breadcrumb-B-9G347O.mjs} +2 -4
- package/dist/button/index.mjs +3 -4
- package/dist/{button-0N61fmAR.mjs → button-BllvE9Lm.mjs} +3 -5
- package/dist/{button-D6AORsOz.mjs → button-D3RrsMfQ.mjs} +2 -4
- package/dist/{link-button-Cby0p4LW.mjs → button-fO8nazJE.mjs} +3 -5
- package/dist/button-group/index.mjs +2 -5
- package/dist/{button-group-BDk8btAy.mjs → button-group-CYPka2zz.mjs} +3 -5
- package/dist/calendar/index.mjs +2 -5
- package/dist/{calendar-BtfraIvX.mjs → calendar-DEkCw7I1.mjs} +4 -6
- package/dist/{calendar-date-picker-B9mxJM7f.mjs → calendar-date-picker-CDT-8Ha8.mjs} +8 -9
- package/dist/card/index.mjs +2 -4
- package/dist/{card-BiHXFt4s.mjs → card-DKG1Cwlj.mjs} +3 -6
- package/dist/chart/index.mjs +2 -4
- package/dist/{chart-CL0i-xIt.mjs → chart-CUa21ynK.mjs} +2 -4
- package/dist/checkbox/index.mjs +2 -4
- package/dist/{checkbox-CQrjygFt.mjs → checkbox-I5BvrMPe.mjs} +3 -6
- package/dist/{close.icon-D2r5q3bj.mjs → close.icon-HCfS4Y-N.mjs} +2 -4
- package/dist/{cn-DWCc1QRE.mjs → cn-D2KYQ917.mjs} +1 -3
- package/dist/code-editor/index.mjs +2 -0
- package/dist/{col-C9PDhvm5.mjs → col-1T0Q3SlH.mjs} +2 -7
- package/dist/collapsible/index.mjs +2 -3
- package/dist/{collapsible-Dw71o2um.mjs → collapsible-CUphkSBt.mjs} +1 -3
- package/dist/combobox/index.mjs +2 -0
- package/dist/combobox-B-C9lJeD.mjs +97 -0
- package/dist/command/index.mjs +2 -5
- package/dist/{command-DVroicgn.mjs → command-DqHWukGK.mjs} +3 -5
- package/dist/components/features/autocomplete/autocomplete.d.ts +1 -1
- package/dist/components/features/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/features/autocomplete/autocomplete.types.d.ts +2 -0
- package/dist/components/features/autocomplete/autocomplete.types.d.ts.map +1 -1
- package/dist/components/features/autosearch/autosearch.d.ts +35 -0
- package/dist/components/features/autosearch/autosearch.d.ts.map +1 -0
- package/dist/components/features/autosearch/autosearch.types.d.ts +51 -0
- package/dist/components/features/autosearch/autosearch.types.d.ts.map +1 -0
- package/dist/components/features/autosearch/index.d.ts +3 -0
- package/dist/components/features/autosearch/index.d.ts.map +1 -0
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts +2 -1
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts.map +1 -1
- package/dist/components/features/code-editor/code-editor-tabs.d.ts +63 -0
- package/dist/components/features/code-editor/code-editor-tabs.d.ts.map +1 -0
- package/dist/components/features/code-editor/code-editor.d.ts +58 -0
- package/dist/components/features/code-editor/code-editor.d.ts.map +1 -0
- package/dist/components/features/code-editor/index.d.ts +6 -0
- package/dist/components/features/code-editor/index.d.ts.map +1 -0
- package/dist/components/features/code-editor/lib/editor.d.ts +7 -0
- package/dist/components/features/code-editor/lib/editor.d.ts.map +1 -0
- package/dist/components/features/code-editor/types.d.ts +98 -0
- package/dist/components/features/code-editor/types.d.ts.map +1 -0
- package/dist/components/features/combobox/combobox.d.ts +27 -0
- package/dist/components/features/combobox/combobox.d.ts.map +1 -0
- package/dist/components/features/combobox/index.d.ts +3 -0
- package/dist/components/features/combobox/index.d.ts.map +1 -0
- package/dist/components/features/combobox/types.d.ts +84 -0
- package/dist/components/features/combobox/types.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/date-time-picker.d.ts +9 -0
- package/dist/components/features/date-time-picker/date-time-picker.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/index.d.ts +3 -0
- package/dist/components/features/date-time-picker/index.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/types.d.ts +59 -0
- package/dist/components/features/date-time-picker/types.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/utils/format.d.ts +13 -0
- package/dist/components/features/date-time-picker/utils/format.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/utils/index.d.ts +3 -0
- package/dist/components/features/date-time-picker/utils/index.d.ts.map +1 -0
- package/dist/components/features/date-time-picker/utils/timezone.d.ts +23 -0
- package/dist/components/features/date-time-picker/utils/timezone.d.ts.map +1 -0
- package/dist/components/features/form/adapter-context.d.ts +17 -0
- package/dist/components/features/form/adapter-context.d.ts.map +1 -0
- package/dist/components/features/form/adapter-types.d.ts +120 -0
- package/dist/components/features/form/adapter-types.d.ts.map +1 -0
- package/dist/components/features/form/adapters/conform/conform-adapter.d.ts +9 -0
- package/dist/components/features/form/adapters/conform/conform-adapter.d.ts.map +1 -0
- package/dist/components/features/form/adapters/conform/conform-provider.d.ts +22 -0
- package/dist/components/features/form/adapters/conform/conform-provider.d.ts.map +1 -0
- package/dist/components/features/form/adapters/conform/index.d.ts +3 -0
- package/dist/components/features/form/adapters/conform/index.d.ts.map +1 -0
- package/dist/components/features/form/adapters/rhf/index.d.ts +3 -0
- package/dist/components/features/form/adapters/rhf/index.d.ts.map +1 -0
- package/dist/components/features/form/adapters/rhf/rhf-adapter.d.ts +10 -0
- package/dist/components/features/form/adapters/rhf/rhf-adapter.d.ts.map +1 -0
- package/dist/components/features/form/adapters/rhf/rhf-provider.d.ts +22 -0
- package/dist/components/features/form/adapters/rhf/rhf-provider.d.ts.map +1 -0
- package/dist/components/features/form/components/form-autocomplete.d.ts.map +1 -1
- package/dist/components/features/form/components/form-autosearch.d.ts +37 -0
- package/dist/components/features/form/components/form-autosearch.d.ts.map +1 -0
- package/dist/components/features/form/components/form-checkbox.d.ts.map +1 -1
- package/dist/components/features/form/components/form-combobox.d.ts +80 -0
- package/dist/components/features/form/components/form-combobox.d.ts.map +1 -0
- package/dist/components/features/form/components/form-copy-box.d.ts +3 -0
- package/dist/components/features/form/components/form-copy-box.d.ts.map +1 -1
- package/dist/components/features/form/components/form-custom.d.ts.map +1 -1
- package/dist/components/features/form/components/form-date-picker.d.ts +40 -0
- package/dist/components/features/form/components/form-date-picker.d.ts.map +1 -0
- package/dist/components/features/form/components/form-date-time-picker.d.ts +39 -0
- package/dist/components/features/form/components/form-date-time-picker.d.ts.map +1 -0
- package/dist/components/features/form/components/form-dialog.d.ts.map +1 -1
- package/dist/components/features/form/components/form-field-array.d.ts +5 -17
- package/dist/components/features/form/components/form-field-array.d.ts.map +1 -1
- package/dist/components/features/form/components/form-field.d.ts +7 -21
- package/dist/components/features/form/components/form-field.d.ts.map +1 -1
- package/dist/components/features/form/components/form-input-group.d.ts +4 -4
- package/dist/components/features/form/components/form-input-group.d.ts.map +1 -1
- package/dist/components/features/form/components/form-input.d.ts.map +1 -1
- package/dist/components/features/form/components/form-radio-group.d.ts.map +1 -1
- package/dist/components/features/form/components/form-root.d.ts +5 -25
- package/dist/components/features/form/components/form-root.d.ts.map +1 -1
- package/dist/components/features/form/components/form-select.d.ts.map +1 -1
- package/dist/components/features/form/components/form-switch.d.ts.map +1 -1
- package/dist/components/features/form/components/form-textarea.d.ts.map +1 -1
- package/dist/components/features/form/components/form-time-picker.d.ts +21 -0
- package/dist/components/features/form/components/form-time-picker.d.ts.map +1 -0
- package/dist/components/features/form/components/form-transfer.d.ts +37 -0
- package/dist/components/features/form/components/form-transfer.d.ts.map +1 -0
- package/dist/components/features/form/components/index.d.ts +7 -1
- package/dist/components/features/form/components/index.d.ts.map +1 -1
- package/dist/components/features/form/components/stepper/form-stepper.d.ts.map +1 -1
- package/dist/components/features/form/context/form-context.d.ts +2 -2
- package/dist/components/features/form/context/form-context.d.ts.map +1 -1
- package/dist/components/features/form/hooks/index.d.ts +1 -1
- package/dist/components/features/form/hooks/index.d.ts.map +1 -1
- package/dist/components/features/form/hooks/use-field.d.ts +12 -18
- package/dist/components/features/form/hooks/use-field.d.ts.map +1 -1
- package/dist/components/features/form/hooks/use-form-state.d.ts +36 -0
- package/dist/components/features/form/hooks/use-form-state.d.ts.map +1 -0
- package/dist/components/features/form/hooks/use-watch.d.ts +9 -20
- package/dist/components/features/form/hooks/use-watch.d.ts.map +1 -1
- package/dist/components/features/form/index.d.ts +69 -45
- package/dist/components/features/form/index.d.ts.map +1 -1
- package/dist/components/features/form/stepper/index.d.ts +17 -0
- package/dist/components/features/form/stepper/index.d.ts.map +1 -0
- package/dist/components/features/form/types/index.d.ts +68 -32
- package/dist/components/features/form/types/index.d.ts.map +1 -1
- package/dist/components/features/form/utils/get-field-constraints.d.ts +33 -0
- package/dist/components/features/form/utils/get-field-constraints.d.ts.map +1 -0
- package/dist/components/features/form/utils/get-schema-defaults.d.ts +24 -0
- package/dist/components/features/form/utils/get-schema-defaults.d.ts.map +1 -0
- package/dist/components/features/form/utils/zod-helpers.d.ts +12 -0
- package/dist/components/features/form/utils/zod-helpers.d.ts.map +1 -0
- package/dist/components/features/index.d.ts +1 -0
- package/dist/components/features/index.d.ts.map +1 -1
- package/dist/components/features/time-picker/index.d.ts +3 -0
- package/dist/components/features/time-picker/index.d.ts.map +1 -0
- package/dist/components/features/time-picker/time-picker.d.ts +22 -0
- package/dist/components/features/time-picker/time-picker.d.ts.map +1 -0
- package/dist/components/features/time-picker/types.d.ts +31 -0
- package/dist/components/features/time-picker/types.d.ts.map +1 -0
- package/dist/components/features/transfer/components/index.d.ts +9 -0
- package/dist/components/features/transfer/components/index.d.ts.map +1 -0
- package/dist/components/features/transfer/components/transfer-group.d.ts +7 -0
- package/dist/components/features/transfer/components/transfer-group.d.ts.map +1 -0
- package/dist/components/features/transfer/components/transfer-item.d.ts +10 -0
- package/dist/components/features/transfer/components/transfer-item.d.ts.map +1 -0
- package/dist/components/features/transfer/components/transfer-panel.d.ts +18 -0
- package/dist/components/features/transfer/components/transfer-panel.d.ts.map +1 -0
- package/dist/components/features/transfer/components/transfer-search.d.ts +9 -0
- package/dist/components/features/transfer/components/transfer-search.d.ts.map +1 -0
- package/dist/components/features/transfer/hooks/use-transfer-dnd.d.ts +26 -0
- package/dist/components/features/transfer/hooks/use-transfer-dnd.d.ts.map +1 -0
- package/dist/components/features/transfer/hooks/use-transfer-state.d.ts +20 -0
- package/dist/components/features/transfer/hooks/use-transfer-state.d.ts.map +1 -0
- package/dist/components/features/transfer/index.d.ts +3 -0
- package/dist/components/features/transfer/index.d.ts.map +1 -0
- package/dist/components/features/transfer/transfer.d.ts +6 -0
- package/dist/components/features/transfer/transfer.d.ts.map +1 -0
- package/dist/components/features/transfer/types.d.ts +69 -0
- package/dist/components/features/transfer/types.d.ts.map +1 -0
- package/dist/components/toast.d.ts +2 -0
- package/dist/components/toast.d.ts.map +1 -0
- package/dist/data-table/index.mjs +21 -51
- package/dist/date-picker/index.mjs +3 -10
- package/dist/date-time-picker/index.mjs +2 -0
- package/dist/date-time-picker-BomrW07W.mjs +178 -0
- package/dist/dialog/index.mjs +2 -5
- package/dist/{dialog-B0B3Kbfk.mjs → dialog-Bm2H9lrx.mjs} +4 -6
- package/dist/{dialog-DdrHeboM.mjs → dialog-DASRaFxD.mjs} +2 -4
- package/dist/dropdown/index.mjs +2 -3
- package/dist/{dropdown-Cdx7rOKv.mjs → dropdown-DZiAt-jS.mjs} +3 -5
- package/dist/{dropdown-menu-CdShrDz_.mjs → dropdown-menu-lALvDnab.mjs} +5 -7
- package/dist/dropzone/index.mjs +2 -5
- package/dist/{dropzone-B6kSN3DY.mjs → dropzone-ogtpQ4fy.mjs} +5 -8
- package/dist/empty-content/index.mjs +2 -3
- package/dist/{empty-content-B1lwLr40.mjs → empty-content-C63GPJ5d.mjs} +3 -9
- package/dist/form/adapters/conform/index.mjs +327 -0
- package/dist/form/adapters/rhf/index.mjs +267 -0
- package/dist/form/index.mjs +3 -146
- package/dist/form/stepper/index.mjs +541 -0
- package/dist/form-D8OnRHdd.mjs +1653 -0
- package/dist/form-context-Ccxm-wqL.mjs +17 -0
- package/dist/get-field-constraints-BicgDkfH.mjs +51 -0
- package/dist/grid/index.mjs +2 -3
- package/dist/hooks/index.mjs +3 -4
- package/dist/{use-debounce-MnfjH51L.mjs → hooks-D8r2M2U6.mjs} +1 -3
- package/dist/hover-card/index.mjs +2 -4
- package/dist/{hover-card-CEIauuie.mjs → hover-card-DDWWD5Hx.mjs} +2 -4
- package/dist/{icon-wrapper-BBK4z4tj.mjs → icon-wrapper-DuLp3RM1.mjs} +1 -3
- package/dist/icons/index.mjs +4 -5
- package/dist/index.mjs +66 -71
- package/dist/input/index.mjs +2 -5
- package/dist/{input-DEMoi_8F.mjs → input-DOmNpcQJ.mjs} +2 -4
- package/dist/{input-CYFN0Ap2.mjs → input-FKGqZypx.mjs} +3 -5
- package/dist/input-group/index.mjs +2 -7
- package/dist/{input-group-DJgYpOlq.mjs → input-group-DDtz-RT7.mjs} +5 -7
- package/dist/input-number/index.mjs +2 -6
- package/dist/{input-number-Cuy9CCg_.mjs → input-number-a7uydAsw.mjs} +4 -6
- package/dist/input-with-addons/index.mjs +28 -3
- package/dist/label/index.mjs +2 -4
- package/dist/{label-mOg07fuQ.mjs → label-cnAhY-ej.mjs} +3 -6
- package/dist/loader-overlay/index.mjs +2 -3
- package/dist/{loader-overlay-8IWX_1Ga.mjs → loader-overlay-BTFdkp7W.mjs} +3 -5
- package/dist/map/index.mjs +2 -14
- package/dist/{map-CaI1EshG.mjs → map-CWIQ-eql.mjs} +10 -14
- package/dist/{map-leaflet-imports-J7w1V7mh.mjs → map-leaflet-imports-CRSKA79m.mjs} +1 -2
- package/dist/more-actions/index.mjs +2 -5
- package/dist/{more-actions-BO5ikUxY.mjs → more-actions-ILnEZq_E.mjs} +5 -7
- package/dist/nprogress/index.mjs +1 -3
- package/dist/page-title/index.mjs +2 -3
- package/dist/{page-title-DWteBy1E.mjs → page-title-ChsnpBiH.mjs} +2 -4
- package/dist/popover/index.mjs +2 -4
- package/dist/{popover-ugw5MpuT.mjs → popover-FJAcbYoH.mjs} +2 -4
- package/dist/radio-group/index.mjs +2 -4
- package/dist/{radio-group-_gMymwnb.mjs → radio-group-CiITR0LO.mjs} +3 -6
- package/dist/select/index.mjs +2 -4
- package/dist/{select-BZOKWjlH.mjs → select-CiLR_DiQ.mjs} +3 -6
- package/dist/separator/index.mjs +2 -4
- package/dist/{separator-BzyALya2.mjs → separator-DXVTncCK.mjs} +2 -4
- package/dist/sheet/index.mjs +3 -5
- package/dist/{sheet-BX6lae56.mjs → sheet-BzXksqYY.mjs} +4 -6
- package/dist/{sheet-DAcFjaGw.mjs → sheet-Di3b-oPu.mjs} +2 -4
- package/dist/sidebar/index.mjs +2 -10
- package/dist/{sidebar-B3EV33mG.mjs → sidebar-BnhnjvfO.mjs} +10 -14
- package/dist/skeleton/index.mjs +2 -5
- package/dist/{skeleton-2vQ0vFQk.mjs → skeleton-BKl4mfJt.mjs} +2 -4
- package/dist/{skeleton-BgOwIgE0.mjs → skeleton-D1MUhAVo.mjs} +3 -5
- package/dist/spinner/index.mjs +2 -4
- package/dist/{spinner-osyXAlhr.mjs → spinner-OyOf9-Yu.mjs} +2 -4
- package/dist/{spinner.icon-C0MbtgqX.mjs → spinner.icon-C-vjSM6o.mjs} +2 -4
- package/dist/stepper/index.mjs +2 -5
- package/dist/{stepper-BMsn7I78.mjs → stepper-DvIOp0hh.mjs} +3 -5
- package/dist/switch/index.mjs +2 -4
- package/dist/{switch-C60FpEal.mjs → switch-DQJQhPIQ.mjs} +3 -6
- package/dist/table/index.mjs +2 -4
- package/dist/{table-Cl3UzIhI.mjs → table-Cdsh-39-.mjs} +2 -4
- package/dist/tabs/index.mjs +50 -3
- package/dist/tag-input/index.mjs +2 -5
- package/dist/{tag-input-DR2gukhL.mjs → tag-input-T9cUX9-G.mjs} +5 -7
- package/dist/task-queue/index.mjs +2 -7
- package/dist/{task-queue-dropdown-C9KHKbGh.mjs → task-queue-dropdown-Wcbj-f0V.mjs} +10 -30
- package/dist/textarea/index.mjs +2 -5
- package/dist/{textarea-CVo38n3S.mjs → textarea-94vq_G_S.mjs} +2 -4
- package/dist/{textarea-CZF5n57i.mjs → textarea-BwD-MmTV.mjs} +3 -5
- package/dist/theme/index.mjs +2 -3
- package/dist/{theme.provider-TUHlMsjM.mjs → themes-DG1md8FI.mjs} +1 -6
- package/dist/time-picker/index.mjs +2 -0
- package/dist/time-picker-BoF7pZZ2.mjs +43 -0
- package/dist/{to-api-format-naIpF-NI.mjs → to-api-format-Bh3c01gr.mjs} +9 -18
- package/dist/toast/index.mjs +3 -3
- package/dist/{use-toast-By9HuFwP.mjs → toast-BWnN5fax.mjs} +5 -42
- package/dist/toast-DpxlFNNx.mjs +37 -0
- package/dist/tooltip/index.mjs +2 -4
- package/dist/{tooltip-CuX2jQA9.mjs → tooltip-Cruvl5F6.mjs} +3 -6
- package/dist/transfer/index.mjs +2 -0
- package/dist/transfer-B2n8pgEQ.mjs +260 -0
- package/dist/types-BZNk3q65.mjs +357 -0
- package/dist/typography/index.mjs +2 -3
- package/dist/{typography-Iap9fU5P.mjs → typography-ClB8k55E.mjs} +2 -4
- package/dist/{use-copy-to-clipboard-n29wJwvW.mjs → use-copy-to-clipboard-uNeeVHC4.mjs} +2 -4
- package/dist/utils/index.mjs +2 -3
- package/dist/{utils-DJboNGQM.mjs → utils-C8KwMfT_.mjs} +1 -3
- package/dist/visually-hidden/index.mjs +2 -3
- package/dist/{visuallyhidden-BJsQCmg-.mjs → visuallyhidden-BLUsJpYH.mjs} +1 -3
- package/package.json +85 -3
- package/dist/input-with-addons-B8rzNhpq.mjs +0 -30
- package/dist/tabs-DJU7JA3h.mjs +0 -52
- package/dist/use-stepper-DigoyHhX.mjs +0 -2017
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { t as cn } from "../../cn-D2KYQ917.mjs";
|
|
2
|
+
import { t as Button } from "../../button-BllvE9Lm.mjs";
|
|
3
|
+
import { n as useFormContext, t as FormProvider } from "../../form-context-Ccxm-wqL.mjs";
|
|
4
|
+
import { n as useAdapter } from "../../adapter-context-rWveHhDd.mjs";
|
|
5
|
+
import { t as defineStepper } from "../../stepper-DvIOp0hh.mjs";
|
|
6
|
+
import { CheckIcon } from "lucide-react";
|
|
7
|
+
import * as React$1 from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
//#region src/components/features/form/components/stepper/form-stepper.tsx
|
|
11
|
+
const FormStepperContext = React$1.createContext(null);
|
|
12
|
+
function useFormStepperContext() {
|
|
13
|
+
const context = React$1.use(FormStepperContext);
|
|
14
|
+
if (!context) throw new Error("useFormStepperContext must be used within a Form.Stepper component");
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Recursively unwrap ZodIntersection (from .and()) to extract the base ZodObject.
|
|
19
|
+
*
|
|
20
|
+
* Zod v4 schema types use `def.type` as a string discriminant:
|
|
21
|
+
* - "intersection" (from .and()): merge left + right base objects
|
|
22
|
+
* - "object": return directly
|
|
23
|
+
*
|
|
24
|
+
* Note: In Zod v4, .superRefine() and .refine() return `this` (no wrapper),
|
|
25
|
+
* so only ZodIntersection needs unwrapping.
|
|
26
|
+
*/
|
|
27
|
+
function getBaseObject(schema) {
|
|
28
|
+
if (schema.def.type === "intersection") {
|
|
29
|
+
const intersectionDef = schema.def;
|
|
30
|
+
const left = getBaseObject(intersectionDef.left);
|
|
31
|
+
const right = getBaseObject(intersectionDef.right);
|
|
32
|
+
return left.merge(right);
|
|
33
|
+
}
|
|
34
|
+
if (schema.def.type !== "object") return z.object({});
|
|
35
|
+
return schema;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Merge multiple zod schemas into one ZodObject for HTML constraint generation.
|
|
39
|
+
* Handles ZodIntersection (.and()) by unwrapping to base ZodObject shapes.
|
|
40
|
+
* Per-step validation still uses the original schemas with all refinements intact.
|
|
41
|
+
*/
|
|
42
|
+
function mergeSchemas(steps) {
|
|
43
|
+
if (steps.length === 0) throw new Error("Form.Stepper requires at least one step");
|
|
44
|
+
return steps.reduce((acc, step, index) => {
|
|
45
|
+
const base = getBaseObject(step.schema);
|
|
46
|
+
if (index === 0) return base;
|
|
47
|
+
return acc.merge(base);
|
|
48
|
+
}, {});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Convert StepConfig[] to Stepperize step format
|
|
52
|
+
*/
|
|
53
|
+
function toStepperizeSteps(steps) {
|
|
54
|
+
return steps.map((step) => ({
|
|
55
|
+
id: step.id,
|
|
56
|
+
label: step.label,
|
|
57
|
+
description: step.description
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Form.Stepper - Multi-step form container
|
|
62
|
+
*
|
|
63
|
+
* Uses Stepperize internally for step navigation and a single Conform form
|
|
64
|
+
* instance for all steps. Schemas are auto-merged for unified validation.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* const steps = [
|
|
69
|
+
* { id: 'account', label: 'Account', schema: accountSchema },
|
|
70
|
+
* { id: 'profile', label: 'Profile', schema: profileSchema },
|
|
71
|
+
* ];
|
|
72
|
+
*
|
|
73
|
+
* <Form.Stepper steps={steps} onComplete={handleComplete}>
|
|
74
|
+
* <Form.StepperNavigation />
|
|
75
|
+
*
|
|
76
|
+
* <Form.Step id="account">
|
|
77
|
+
* <Form.Field name="email" label="Email" required>
|
|
78
|
+
* <Form.Input type="email" />
|
|
79
|
+
* </Form.Field>
|
|
80
|
+
* </Form.Step>
|
|
81
|
+
*
|
|
82
|
+
* <Form.Step id="profile">
|
|
83
|
+
* <Form.Field name="name" label="Full Name" required>
|
|
84
|
+
* <Form.Input />
|
|
85
|
+
* </Form.Field>
|
|
86
|
+
* </Form.Step>
|
|
87
|
+
*
|
|
88
|
+
* <Form.StepperControls />
|
|
89
|
+
* </Form.Stepper>
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
function FormStepper({ steps, children, onComplete, onStepChange, initialStep, className, defaultValues, id, formComponent }) {
|
|
93
|
+
const stepperDef = React$1.useMemo(() => {
|
|
94
|
+
return defineStepper(...toStepperizeSteps(steps));
|
|
95
|
+
}, [steps]);
|
|
96
|
+
const initialStepIndex = React$1.useMemo(() => {
|
|
97
|
+
if (!initialStep) return void 0;
|
|
98
|
+
const index = steps.findIndex((s) => s.id === initialStep);
|
|
99
|
+
return index >= 0 ? steps[index].id : void 0;
|
|
100
|
+
}, [initialStep, steps]);
|
|
101
|
+
const { Stepper } = stepperDef;
|
|
102
|
+
const providerProps = initialStepIndex ? { initialStep: initialStepIndex } : {};
|
|
103
|
+
return /* @__PURE__ */ jsx(Stepper.Provider, {
|
|
104
|
+
...providerProps,
|
|
105
|
+
children: /* @__PURE__ */ jsx(FormStepperContent, {
|
|
106
|
+
steps,
|
|
107
|
+
stepperDef,
|
|
108
|
+
onComplete,
|
|
109
|
+
onStepChange,
|
|
110
|
+
className,
|
|
111
|
+
defaultValues,
|
|
112
|
+
id,
|
|
113
|
+
formComponent,
|
|
114
|
+
children
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
FormStepper.displayName = "Form.Stepper";
|
|
119
|
+
function FormStepperContent({ steps, stepperDef, children, onComplete, onStepChange, className, defaultValues, id, formComponent }) {
|
|
120
|
+
const { useStepper } = stepperDef;
|
|
121
|
+
const stepper = useStepper();
|
|
122
|
+
return /* @__PURE__ */ jsx(StepForm, {
|
|
123
|
+
steps,
|
|
124
|
+
stepper,
|
|
125
|
+
currentStepConfig: React$1.useMemo(() => steps.find((s) => s.id === stepper.state.current.data.id) ?? steps[0], [steps, stepper.state.current.data.id]),
|
|
126
|
+
combinedSchema: React$1.useMemo(() => mergeSchemas(steps), [steps]),
|
|
127
|
+
storedValues: React$1.useMemo(() => {
|
|
128
|
+
const allMetadata = steps.reduce((acc, step) => ({
|
|
129
|
+
...acc,
|
|
130
|
+
...stepper.metadata.get(step.id) || {}
|
|
131
|
+
}), {});
|
|
132
|
+
return {
|
|
133
|
+
...defaultValues,
|
|
134
|
+
...allMetadata
|
|
135
|
+
};
|
|
136
|
+
}, [
|
|
137
|
+
steps,
|
|
138
|
+
stepper,
|
|
139
|
+
defaultValues,
|
|
140
|
+
stepper.state.current.data.id
|
|
141
|
+
]),
|
|
142
|
+
onComplete,
|
|
143
|
+
onStepChange,
|
|
144
|
+
className,
|
|
145
|
+
id,
|
|
146
|
+
formComponent,
|
|
147
|
+
children
|
|
148
|
+
}, stepper.state.current.data.id);
|
|
149
|
+
}
|
|
150
|
+
function StepForm({ steps, stepper, currentStepConfig, combinedSchema: _combinedSchema, storedValues, children, onComplete, onStepChange, className, id, formComponent: FormComp = "form" }) {
|
|
151
|
+
const adapter = useAdapter();
|
|
152
|
+
const [isSubmitting, setIsSubmitting] = React$1.useState(false);
|
|
153
|
+
const formRef = React$1.useRef(null);
|
|
154
|
+
const currentIndex = stepper.lookup.getIndex(stepper.state.current.data.id);
|
|
155
|
+
const handleStepSubmit = React$1.useCallback(async (data) => {
|
|
156
|
+
stepper.metadata.set(stepper.state.current.data.id, data);
|
|
157
|
+
if (stepper.state.isLast) {
|
|
158
|
+
setIsSubmitting(true);
|
|
159
|
+
try {
|
|
160
|
+
await onComplete({
|
|
161
|
+
...steps.reduce((acc, step) => ({
|
|
162
|
+
...acc,
|
|
163
|
+
...stepper.metadata.get(step.id) || {}
|
|
164
|
+
}), {}),
|
|
165
|
+
...data
|
|
166
|
+
});
|
|
167
|
+
} catch {} finally {
|
|
168
|
+
setIsSubmitting(false);
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
const nextStepId = stepper.lookup.getNext(stepper.state.current.data.id)?.id;
|
|
172
|
+
if (nextStepId) {
|
|
173
|
+
stepper.navigation.goTo(nextStepId);
|
|
174
|
+
onStepChange?.(nextStepId, "next");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}, [
|
|
178
|
+
stepper,
|
|
179
|
+
steps,
|
|
180
|
+
onComplete,
|
|
181
|
+
onStepChange
|
|
182
|
+
]);
|
|
183
|
+
const instance = adapter.useCreateForm({
|
|
184
|
+
schema: currentStepConfig.schema,
|
|
185
|
+
defaultValues: storedValues,
|
|
186
|
+
mode: "onSubmit",
|
|
187
|
+
id: `${id ?? "stepper"}-${currentStepConfig.id}`,
|
|
188
|
+
onSubmit: handleStepSubmit,
|
|
189
|
+
formRef
|
|
190
|
+
});
|
|
191
|
+
const next = React$1.useCallback(() => {
|
|
192
|
+
formRef.current?.requestSubmit();
|
|
193
|
+
}, []);
|
|
194
|
+
const prev = React$1.useCallback(() => {
|
|
195
|
+
const currentValues = instance.getValues();
|
|
196
|
+
if (Object.keys(currentValues).length > 0) stepper.metadata.set(stepper.state.current.data.id, currentValues);
|
|
197
|
+
const prevStepId = stepper.lookup.getPrev(stepper.state.current.data.id)?.id;
|
|
198
|
+
if (prevStepId) {
|
|
199
|
+
stepper.navigation.goTo(prevStepId);
|
|
200
|
+
onStepChange?.(prevStepId, "prev");
|
|
201
|
+
}
|
|
202
|
+
}, [
|
|
203
|
+
instance,
|
|
204
|
+
stepper,
|
|
205
|
+
onStepChange
|
|
206
|
+
]);
|
|
207
|
+
const goTo = React$1.useCallback((stepId) => {
|
|
208
|
+
if (stepper.lookup.getIndex(stepId) < currentIndex) {
|
|
209
|
+
const currentValues = instance.getValues();
|
|
210
|
+
if (Object.keys(currentValues).length > 0) stepper.metadata.set(stepper.state.current.data.id, currentValues);
|
|
211
|
+
stepper.navigation.goTo(stepId);
|
|
212
|
+
onStepChange?.(stepId, "prev");
|
|
213
|
+
}
|
|
214
|
+
}, [
|
|
215
|
+
instance,
|
|
216
|
+
stepper,
|
|
217
|
+
currentIndex,
|
|
218
|
+
onStepChange
|
|
219
|
+
]);
|
|
220
|
+
const getStepData = React$1.useCallback((stepId) => stepper.metadata.get(stepId), [stepper]);
|
|
221
|
+
const getAllStepData = React$1.useCallback(() => {
|
|
222
|
+
return steps.reduce((acc, step) => ({
|
|
223
|
+
...acc,
|
|
224
|
+
...stepper.metadata.get(step.id) || {}
|
|
225
|
+
}), {});
|
|
226
|
+
}, [steps, stepper]);
|
|
227
|
+
const stepperContextValue = React$1.useMemo(() => ({
|
|
228
|
+
steps,
|
|
229
|
+
current: currentStepConfig,
|
|
230
|
+
currentIndex,
|
|
231
|
+
next,
|
|
232
|
+
prev,
|
|
233
|
+
goTo,
|
|
234
|
+
isFirst: stepper.state.isFirst,
|
|
235
|
+
isLast: stepper.state.isLast,
|
|
236
|
+
getStepData,
|
|
237
|
+
getAllStepData,
|
|
238
|
+
utils: { getIndex: (stepId) => stepper.lookup.getIndex(stepId) }
|
|
239
|
+
}), [
|
|
240
|
+
steps,
|
|
241
|
+
currentStepConfig,
|
|
242
|
+
currentIndex,
|
|
243
|
+
stepper,
|
|
244
|
+
next,
|
|
245
|
+
prev,
|
|
246
|
+
goTo,
|
|
247
|
+
getStepData,
|
|
248
|
+
getAllStepData
|
|
249
|
+
]);
|
|
250
|
+
const contextValue = React$1.useMemo(() => ({
|
|
251
|
+
form: instance,
|
|
252
|
+
fields: instance.fields,
|
|
253
|
+
isSubmitting,
|
|
254
|
+
isDirty: instance.formState.isDirty,
|
|
255
|
+
isValid: instance.formState.isValid,
|
|
256
|
+
isSubmitted: instance.formState.isSubmitted,
|
|
257
|
+
submitCount: instance.formState.submitCount,
|
|
258
|
+
dirtyFields: instance.formState.dirtyFields,
|
|
259
|
+
touchedFields: instance.formState.touchedFields,
|
|
260
|
+
submit: () => formRef.current?.requestSubmit(),
|
|
261
|
+
reset: () => instance.reset(),
|
|
262
|
+
formId: instance.id
|
|
263
|
+
}), [
|
|
264
|
+
instance,
|
|
265
|
+
isSubmitting,
|
|
266
|
+
instance.formState
|
|
267
|
+
]);
|
|
268
|
+
const renderProps = {
|
|
269
|
+
steps,
|
|
270
|
+
current: currentStepConfig,
|
|
271
|
+
currentIndex,
|
|
272
|
+
next,
|
|
273
|
+
prev,
|
|
274
|
+
goTo,
|
|
275
|
+
isFirst: stepper.state.isFirst,
|
|
276
|
+
isLast: stepper.state.isLast,
|
|
277
|
+
getStepData,
|
|
278
|
+
getAllStepData
|
|
279
|
+
};
|
|
280
|
+
const resolvedChildren = typeof children === "function" ? children(renderProps) : children;
|
|
281
|
+
return /* @__PURE__ */ jsx(FormStepperContext, {
|
|
282
|
+
value: stepperContextValue,
|
|
283
|
+
children: /* @__PURE__ */ jsx(FormProvider, {
|
|
284
|
+
value: contextValue,
|
|
285
|
+
children: /* @__PURE__ */ jsx(adapter.FormProvider, {
|
|
286
|
+
instance,
|
|
287
|
+
children: /* @__PURE__ */ jsx(FormComp, {
|
|
288
|
+
ref: formRef,
|
|
289
|
+
...instance.formProps,
|
|
290
|
+
className: cn("space-y-6", className),
|
|
291
|
+
autoComplete: "off",
|
|
292
|
+
noValidate: true,
|
|
293
|
+
onSubmit: (e) => {
|
|
294
|
+
e.stopPropagation();
|
|
295
|
+
const adapterSubmit = instance.formProps.onSubmit;
|
|
296
|
+
adapterSubmit?.(e);
|
|
297
|
+
},
|
|
298
|
+
children: resolvedChildren
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
})
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/components/features/form/components/stepper/form-step.tsx
|
|
306
|
+
/**
|
|
307
|
+
* Form.Step - Individual step content container
|
|
308
|
+
*
|
|
309
|
+
* Only renders its children when the step is active.
|
|
310
|
+
* Works with the single-form architecture - fields remain registered
|
|
311
|
+
* even when unmounted, preserving their values.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```tsx
|
|
315
|
+
* <Form.Step id="account">
|
|
316
|
+
* <Form.Field name="email" label="Email" required>
|
|
317
|
+
* <Form.Input type="email" />
|
|
318
|
+
* </Form.Field>
|
|
319
|
+
* </Form.Step>
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
function FormStep({ id, children }) {
|
|
323
|
+
const { current } = useFormStepperContext();
|
|
324
|
+
if (current.id !== id) return null;
|
|
325
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
326
|
+
}
|
|
327
|
+
FormStep.displayName = "Form.Step";
|
|
328
|
+
//#endregion
|
|
329
|
+
//#region src/components/features/form/components/stepper/stepper-controls.tsx
|
|
330
|
+
/**
|
|
331
|
+
* Form.StepperControls - Navigation buttons (Previous/Next/Submit)
|
|
332
|
+
*
|
|
333
|
+
* Provides Previous and Next/Submit buttons for navigating between steps.
|
|
334
|
+
* The Next button triggers form validation before advancing.
|
|
335
|
+
* The Previous button navigates back without validation.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```tsx
|
|
339
|
+
* <Form.StepperControls
|
|
340
|
+
* prevLabel={(isFirst) => isFirst ? 'Cancel' : 'Previous'}
|
|
341
|
+
* nextLabel={(isLast) => isLast ? 'Submit' : 'Next'}
|
|
342
|
+
* loadingText="Creating..."
|
|
343
|
+
* onCancel={() => setOpen(false)}
|
|
344
|
+
* />
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* @example With external loading state
|
|
348
|
+
* ```tsx
|
|
349
|
+
* <Form.StepperControls
|
|
350
|
+
* loading={fetcher.state === 'submitting'}
|
|
351
|
+
* disabled={!isValid}
|
|
352
|
+
* loadingText="Saving..."
|
|
353
|
+
* />
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
function StepperControls({ prevLabel = "Previous", nextLabel = (isLast) => isLast ? "Submit" : "Next", loadingText = "Submitting...", showPrev = true, loading, disabled, onPrev, onCancel, className }) {
|
|
357
|
+
const { prev, isFirst, isLast } = useFormStepperContext();
|
|
358
|
+
const { isSubmitting: formIsSubmitting } = useFormContext();
|
|
359
|
+
const isLoading = loading ?? formIsSubmitting;
|
|
360
|
+
const isDisabled = disabled ?? false;
|
|
361
|
+
const getPrevLabel = () => {
|
|
362
|
+
if (typeof prevLabel === "function") return prevLabel(isFirst);
|
|
363
|
+
return prevLabel;
|
|
364
|
+
};
|
|
365
|
+
const getNextLabel = () => {
|
|
366
|
+
if (typeof nextLabel === "function") return nextLabel(isLast);
|
|
367
|
+
return nextLabel;
|
|
368
|
+
};
|
|
369
|
+
const handlePrev = () => {
|
|
370
|
+
if (isFirst && onCancel) onCancel();
|
|
371
|
+
else {
|
|
372
|
+
onPrev?.();
|
|
373
|
+
prev();
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
377
|
+
className: cn("flex items-center justify-between gap-3", className),
|
|
378
|
+
children: [/* @__PURE__ */ jsx("div", { children: showPrev && /* @__PURE__ */ jsx(Button, {
|
|
379
|
+
htmlType: "button",
|
|
380
|
+
type: "quaternary",
|
|
381
|
+
theme: "outline",
|
|
382
|
+
size: "small",
|
|
383
|
+
onClick: handlePrev,
|
|
384
|
+
disabled: isLoading || isDisabled,
|
|
385
|
+
children: getPrevLabel()
|
|
386
|
+
}) }), /* @__PURE__ */ jsx(Button, {
|
|
387
|
+
htmlType: "submit",
|
|
388
|
+
type: "primary",
|
|
389
|
+
size: "small",
|
|
390
|
+
loading: isLoading,
|
|
391
|
+
disabled: isLoading || isDisabled,
|
|
392
|
+
children: isLoading && isLast ? loadingText : getNextLabel()
|
|
393
|
+
})]
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
StepperControls.displayName = "Form.StepperControls";
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region src/components/features/form/components/stepper/stepper-navigation.tsx
|
|
399
|
+
/**
|
|
400
|
+
* Form.StepperNavigation - Step indicators/progress
|
|
401
|
+
*
|
|
402
|
+
* Displays visual step indicators showing current progress through the form.
|
|
403
|
+
* Supports horizontal and vertical variants with optional label orientation.
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```tsx
|
|
407
|
+
* <Form.StepperNavigation variant="horizontal" labelOrientation="vertical" />
|
|
408
|
+
* ```
|
|
409
|
+
*/
|
|
410
|
+
function StepperNavigation({ variant = "horizontal", labelOrientation = "vertical", className }) {
|
|
411
|
+
const { steps, currentIndex } = useFormStepperContext();
|
|
412
|
+
if (variant === "horizontal" && labelOrientation === "vertical") return /* @__PURE__ */ jsx("nav", {
|
|
413
|
+
"aria-label": "Form steps",
|
|
414
|
+
className: cn("flex flex-row items-start justify-between", className),
|
|
415
|
+
children: steps.map((step, index) => {
|
|
416
|
+
const isActive = index === currentIndex;
|
|
417
|
+
const isCompleted = index < currentIndex;
|
|
418
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
419
|
+
className: "relative flex flex-1 flex-col items-center",
|
|
420
|
+
children: [
|
|
421
|
+
!(index === steps.length - 1) && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line absolute top-4 right-[calc(-50%+20px)] left-[calc(50%+20px)] h-0.5" }),
|
|
422
|
+
/* @__PURE__ */ jsx("div", {
|
|
423
|
+
className: cn("relative z-10 flex h-8 w-8 items-center justify-center rounded-full border bg-transparent text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
|
|
424
|
+
"aria-current": isActive ? "step" : void 0,
|
|
425
|
+
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary h-4 w-4" }) : index + 1
|
|
426
|
+
}),
|
|
427
|
+
/* @__PURE__ */ jsxs("div", {
|
|
428
|
+
className: "mt-1",
|
|
429
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
430
|
+
className: cn("text-xs font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
|
|
431
|
+
children: step.label
|
|
432
|
+
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
433
|
+
className: "text-muted-foreground mt-0.5 text-xs",
|
|
434
|
+
children: step.description
|
|
435
|
+
})]
|
|
436
|
+
})
|
|
437
|
+
]
|
|
438
|
+
}, step.id);
|
|
439
|
+
})
|
|
440
|
+
});
|
|
441
|
+
if (variant === "horizontal") return /* @__PURE__ */ jsx("nav", {
|
|
442
|
+
"aria-label": "Form steps",
|
|
443
|
+
className: cn("flex flex-row items-center", className),
|
|
444
|
+
children: steps.map((step, index) => {
|
|
445
|
+
const isActive = index === currentIndex;
|
|
446
|
+
const isCompleted = index < currentIndex;
|
|
447
|
+
const isLast = index === steps.length - 1;
|
|
448
|
+
return /* @__PURE__ */ jsxs(React$1.Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
449
|
+
className: "flex items-center",
|
|
450
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
451
|
+
className: cn("flex h-8 w-8 items-center justify-center rounded-full border text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
|
|
452
|
+
"aria-current": isActive ? "step" : void 0,
|
|
453
|
+
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary size-4" }) : index + 1
|
|
454
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
455
|
+
className: "ml-2",
|
|
456
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
457
|
+
className: cn("text-sm font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
|
|
458
|
+
children: step.label
|
|
459
|
+
})
|
|
460
|
+
})]
|
|
461
|
+
}), !isLast && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line mx-4 h-0.5 min-w-8 flex-1" })] }, step.id);
|
|
462
|
+
})
|
|
463
|
+
});
|
|
464
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
465
|
+
"aria-label": "Form steps",
|
|
466
|
+
className: cn("flex flex-col", className),
|
|
467
|
+
children: steps.map((step, index) => {
|
|
468
|
+
const isActive = index === currentIndex;
|
|
469
|
+
const isCompleted = index < currentIndex;
|
|
470
|
+
const isLast = index === steps.length - 1;
|
|
471
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
472
|
+
className: "flex flex-row",
|
|
473
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
474
|
+
className: "flex flex-col items-center",
|
|
475
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
476
|
+
className: cn("flex h-8 w-8 items-center justify-center rounded-full border text-sm font-medium transition-colors", isActive && "border-primary bg-primary text-primary-foreground", isCompleted && "border-tertiary-foreground bg-tertiary-foreground text-tertiary", !isActive && !isCompleted && "border-stepper-label text-stepper-label"),
|
|
477
|
+
"aria-current": isActive ? "step" : void 0,
|
|
478
|
+
children: isCompleted ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-tertiary size-4" }) : index + 1
|
|
479
|
+
}), !isLast && /* @__PURE__ */ jsx("div", { className: "bg-stepper-line my-1 min-h-8 w-0.5 flex-1" })]
|
|
480
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
481
|
+
className: "ml-3 pb-8",
|
|
482
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
483
|
+
className: cn("text-sm font-medium", isActive && "text-foreground", isCompleted && "text-stepper-label", !isActive && !isCompleted && "text-stepper-label"),
|
|
484
|
+
children: step.label
|
|
485
|
+
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
486
|
+
className: "text-muted-foreground mt-0.5 text-xs",
|
|
487
|
+
children: step.description
|
|
488
|
+
})]
|
|
489
|
+
})]
|
|
490
|
+
}, step.id);
|
|
491
|
+
})
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
StepperNavigation.displayName = "Form.StepperNavigation";
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region src/components/features/form/hooks/use-stepper.ts
|
|
497
|
+
/**
|
|
498
|
+
* Hook to access the stepper context
|
|
499
|
+
* Must be used within a Form.Stepper component
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```tsx
|
|
503
|
+
* function StepContent() {
|
|
504
|
+
* const {
|
|
505
|
+
* current,
|
|
506
|
+
* currentIndex,
|
|
507
|
+
* steps,
|
|
508
|
+
* next,
|
|
509
|
+
* prev,
|
|
510
|
+
* goTo,
|
|
511
|
+
* isFirst,
|
|
512
|
+
* isLast,
|
|
513
|
+
* } = useStepper();
|
|
514
|
+
*
|
|
515
|
+
* return (
|
|
516
|
+
* <div>
|
|
517
|
+
* <h2>Step {currentIndex + 1}: {current.label}</h2>
|
|
518
|
+
* <button onClick={prev} disabled={isFirst}>Previous</button>
|
|
519
|
+
* <button onClick={next} disabled={isLast}>Next</button>
|
|
520
|
+
* </div>
|
|
521
|
+
* );
|
|
522
|
+
* }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
function useStepper() {
|
|
526
|
+
const context = useFormStepperContext();
|
|
527
|
+
return {
|
|
528
|
+
steps: context.steps,
|
|
529
|
+
current: context.current,
|
|
530
|
+
currentIndex: context.currentIndex,
|
|
531
|
+
next: context.next,
|
|
532
|
+
prev: context.prev,
|
|
533
|
+
goTo: context.goTo,
|
|
534
|
+
isFirst: context.isFirst,
|
|
535
|
+
isLast: context.isLast,
|
|
536
|
+
getStepData: context.getStepData,
|
|
537
|
+
getAllStepData: context.getAllStepData
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
//#endregion
|
|
541
|
+
export { FormStep, FormStepper, StepperControls, StepperNavigation, useStepper };
|