@k3-universe/react-kit 0.0.36 → 0.0.39
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3186 -899
- package/dist/kit/builder/form/hooks/useFormBuilder.d.ts.map +1 -1
- package/dist/kit/builder/section/SectionBuilder.d.ts.map +1 -1
- package/dist/kit/components/keyboard/Keyboard.d.ts +28 -0
- package/dist/kit/components/keyboard/Keyboard.d.ts.map +1 -0
- package/dist/kit/components/keyboard/index.d.ts +5 -0
- package/dist/kit/components/keyboard/index.d.ts.map +1 -0
- package/dist/kit/components/numpad/Numpad.d.ts +26 -0
- package/dist/kit/components/numpad/Numpad.d.ts.map +1 -0
- package/dist/kit/components/numpad/index.d.ts +5 -0
- package/dist/kit/components/numpad/index.d.ts.map +1 -0
- package/dist/kit/themes/base.css +1 -1
- package/dist/kit/themes/clean-slate.css +161 -1
- package/dist/kit/themes/default.css +161 -1
- package/dist/kit/themes/minimal-modern.css +161 -1
- package/dist/kit/themes/spotify.css +161 -1
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/kit/builder/section/SectionBuilder.tsx +22 -4
- package/src/kit/components/keyboard/Keyboard.tsx +916 -0
- package/src/kit/components/keyboard/index.ts +4 -0
- package/src/kit/components/numpad/Numpad.tsx +377 -0
- package/src/kit/components/numpad/index.ts +4 -0
- package/src/shadcn/ui/calendar.tsx +1 -1
- package/src/stories/kit/components/Keyboard.stories.tsx +263 -0
- package/src/stories/kit/components/Numpad.stories.tsx +195 -0
- package/storybook-static/assets/Accordion.stories-KU4JBR8U.js +52 -0
- package/storybook-static/assets/AdminLayout-CPvVCwfY.js +53 -0
- package/storybook-static/assets/AdminLayout.Basic.stories-DkP2UVXe.js +4 -0
- package/storybook-static/assets/AdminLayout.Collapsible.stories-BuuVjtpW.js +4 -0
- package/storybook-static/assets/AdminLayout.Complex.stories-D-k4H0hJ.js +29 -0
- package/storybook-static/assets/AdminLayout.CustomSidebarHeaderComponent.stories-B_0IEDd4.js +9 -0
- package/storybook-static/assets/AdminLayout.CustomSidebarTitleAndIcon.stories-CvAeXUyA.js +4 -0
- package/storybook-static/assets/AdminLayout.HeaderSlots.stories-RBFHoSZK.js +7 -0
- package/storybook-static/assets/Alert.stories-DKxKtIc0.js +27 -0
- package/storybook-static/assets/AlertDialog.stories-BqTpZ_nG.js +43 -0
- package/storybook-static/assets/AspectRatio.stories-DPO9QQ5F.js +22 -0
- package/storybook-static/assets/Autocomplete-Cpg4CaJe.js +56 -0
- package/storybook-static/assets/Autocomplete.stories-CWj4G5fh.js +56 -0
- package/storybook-static/assets/Avatar.stories-DPhov_2g.js +12 -0
- package/storybook-static/assets/Badge.stories-DFKrRdXq.js +12 -0
- package/storybook-static/assets/Breadcrumb.stories-CTE6CZUC.js +25 -0
- package/storybook-static/assets/Button.stories-cbt2InL-.js +26 -0
- package/storybook-static/assets/Calendar.stories-DRhTw_43.js +3 -0
- package/storybook-static/assets/Card.stories-Isf6n_K3.js +15 -0
- package/storybook-static/assets/Carousel.stories-Cmg0I3fR.js +15 -0
- package/storybook-static/assets/Chart.stories-aQ-fNijT.js +126 -0
- package/storybook-static/assets/Checkbox.stories-B7YMXPDc.js +12 -0
- package/storybook-static/assets/Collapsible.stories-BUzl17ZZ.js +18 -0
- package/storybook-static/assets/Combination-BdQWAuko.js +41 -0
- package/storybook-static/assets/Command.stories-DzBlWQs0.js +30 -0
- package/storybook-static/assets/ContextMenu.stories-CJlBQyXc.js +31 -0
- package/storybook-static/assets/DataTable.Basic.stories-BWYKFDmK.js +6 -0
- package/storybook-static/assets/DataTable.Filters.stories-uZdtJk8t.js +21 -0
- package/storybook-static/assets/DataTable.Pagination.stories-C5N1khkp.js +24 -0
- package/storybook-static/assets/DataTable.SelectionAndActions.stories-FhCqZKvO.js +26 -0
- package/storybook-static/assets/DataTable.Sorting.stories-D-k7EtRj.js +6 -0
- package/storybook-static/assets/Dialog.stories-C62AF-Gx.js +54 -0
- package/storybook-static/assets/Dialog.stories-lrjRwOus.js +18 -0
- package/storybook-static/assets/Drawer.stories-CGjkdJeV.js +24 -0
- package/storybook-static/assets/DropdownMenu.stories-DkGClRAA.js +35 -0
- package/storybook-static/assets/Form.ArrayLayouts.stories-C5d_062d.js +130 -0
- package/storybook-static/assets/Form.Autocomplete.stories-CPZPkk4o.js +142 -0
- package/storybook-static/assets/Form.Basic.stories-Bhcu3-3n.js +58 -0
- package/storybook-static/assets/Form.Complex.stories-QnXh5a7Q.js +361 -0
- package/storybook-static/assets/Form.Dynamic.stories-DFW6wIuT.js +502 -0
- package/storybook-static/assets/Form.Simple.stories-BhJcyhbE.js +53 -0
- package/storybook-static/assets/Form.stories-PFNsMYxO.js +3 -0
- package/storybook-static/assets/FormBuilder-BQBBxo_k.js +5 -0
- package/storybook-static/assets/HoverCard.stories-CAlQEVn8.js +21 -0
- package/storybook-static/assets/Input.stories-CEhODt0V.js +16 -0
- package/storybook-static/assets/InputOtp.stories-DSvNP4dS.js +42 -0
- package/storybook-static/assets/Label.stories-B3pa8ZLY.js +14 -0
- package/storybook-static/assets/Login.stories-C7KQkmR_.js +37 -0
- package/storybook-static/assets/Menubar.stories-CHXhSHxc.js +44 -0
- package/storybook-static/assets/MonthPicker.stories-BnrOc4fm.js +99 -0
- package/storybook-static/assets/MonthRangePicker.stories-55Gk1t-7.js +134 -0
- package/storybook-static/assets/NavigationMenu.stories-CXoS080P.js +30 -0
- package/storybook-static/assets/Page.stories-GdSJgZ6-.js +91 -0
- package/storybook-static/assets/Pagination.stories-BEBwqH4N.js +29 -0
- package/storybook-static/assets/Popover.stories-BICy98Cw.js +15 -0
- package/storybook-static/assets/Progress.stories-DECHNOME.js +8 -0
- package/storybook-static/assets/RadioGroup.stories-DA7-uKfV.js +16 -0
- package/storybook-static/assets/Resizable.stories-B99kWkH7.js +25 -0
- package/storybook-static/assets/ScrollArea.stories-BqvUAXqU.js +12 -0
- package/storybook-static/assets/Section.stories-lFMlFBQn.js +277 -0
- package/storybook-static/assets/SectionBuilder-BQW705x0.js +1 -0
- package/storybook-static/assets/Select.stories-BsKyZ6Io.js +17 -0
- package/storybook-static/assets/Separator.stories-BTDOaOM2.js +17 -0
- package/storybook-static/assets/Sheet.stories-Cam1gR6G.js +24 -0
- package/storybook-static/assets/Sidebar.stories-DnOa6G7y.js +106 -0
- package/storybook-static/assets/Skeleton.stories-BQNIuIe5.js +9 -0
- package/storybook-static/assets/Slider.stories-Bslq7hjq.js +6 -0
- package/storybook-static/assets/Sonner.stories-D34pBBtI.js +18 -0
- package/storybook-static/assets/Switch.stories-Puyb1-Bx.js +3 -0
- package/storybook-static/assets/Table.stories-ClZxAhut.js +35 -0
- package/storybook-static/assets/Tabs.stories-CURNTETB.js +10 -0
- package/storybook-static/assets/Textarea.stories-Cf1ZBrWw.js +17 -0
- package/storybook-static/assets/Toggle.stories-CdMHY_bi.js +3 -0
- package/storybook-static/assets/ToggleGroup.stories-BM68m1dX.js +13 -0
- package/storybook-static/assets/Tooltip.stories-DiQv64dM.js +10 -0
- package/storybook-static/assets/accordion-DVgwQcnw.js +1 -0
- package/storybook-static/assets/alert-dialog-DCUEwpqm.js +7 -0
- package/storybook-static/assets/avatar-BzwOE-mi.js +1 -0
- package/storybook-static/assets/axe-HmUsR1st.js +30 -0
- package/storybook-static/assets/badge-BnQWua6u.js +1 -0
- package/storybook-static/assets/button-0oMkiryo.js +1 -0
- package/storybook-static/assets/card-BJpPOzP8.js +1 -0
- package/storybook-static/assets/chart-column-DZGb4ZZS.js +6 -0
- package/storybook-static/assets/check-B9hBGj6o.js +6 -0
- package/storybook-static/assets/checkbox-CyIeaWHX.js +1 -0
- package/storybook-static/assets/chevron-down-D_37S6il.js +6 -0
- package/storybook-static/assets/chevron-left-BBoN0vbI.js +6 -0
- package/storybook-static/assets/chevron-right-B5vIMLxK.js +6 -0
- package/storybook-static/assets/circle-C5Lzx6Nx.js +6 -0
- package/storybook-static/assets/clean-slate-D1HmMFJM.css +1 -0
- package/storybook-static/assets/command-Csa9p8_a.js +6 -0
- package/storybook-static/assets/createLucideIcon-BrHXro7t.js +21 -0
- package/storybook-static/assets/default-CN_Fo1GY.css +1 -0
- package/storybook-static/assets/dependencies-ctrV69dx.js +1 -0
- package/storybook-static/assets/dialog-CsnqITTn.js +1 -0
- package/storybook-static/assets/dropdown-menu-BWxxwPHL.js +1 -0
- package/storybook-static/assets/ellipsis-BRS038RR.js +6 -0
- package/storybook-static/assets/grip-vertical-BxXG8KNA.js +6 -0
- package/storybook-static/assets/iframe-C9bogcIc.css +1 -0
- package/storybook-static/assets/iframe-v7iAhKit.js +1555 -0
- package/storybook-static/assets/index-0-qMRXou.js +1 -0
- package/storybook-static/assets/index-AvwFFKJc.js +1 -0
- package/storybook-static/assets/index-BVDb4dFc.js +1 -0
- package/storybook-static/assets/index-B_qx7A5T.js +1 -0
- package/storybook-static/assets/index-BdQq_4o_.js +1 -0
- package/storybook-static/assets/index-BfiCOk42.js +1 -0
- package/storybook-static/assets/index-Bv9yk470.js +1 -0
- package/storybook-static/assets/index-Bw1A27Kp.js +1 -0
- package/storybook-static/assets/index-ByqivBWx.js +1 -0
- package/storybook-static/assets/index-C9Ta0ZTH.js +1 -0
- package/storybook-static/assets/index-CDY5kTx5.js +1 -0
- package/storybook-static/assets/index-CGnyVRgB.js +1 -0
- package/storybook-static/assets/index-CGrAONsN.js +1 -0
- package/storybook-static/assets/index-CWjrGFAQ.js +1 -0
- package/storybook-static/assets/index-CwBdPBFz.js +9 -0
- package/storybook-static/assets/index-D8RXF03I.js +1 -0
- package/storybook-static/assets/index-DLIxT4Z7.js +1 -0
- package/storybook-static/assets/index-DW48STyt.js +1 -0
- package/storybook-static/assets/index-DbaA6-o1.js +1 -0
- package/storybook-static/assets/index-Dph_5COR.js +1 -0
- package/storybook-static/assets/index-DrN5n71E.js +1 -0
- package/storybook-static/assets/index-Tp9IdbR8.js +1 -0
- package/storybook-static/assets/index-WyF3-wTE.js +9 -0
- package/storybook-static/assets/index-XSmPROEP.js +1 -0
- package/storybook-static/assets/index-Z6wF44KX.js +5 -0
- package/storybook-static/assets/index-_RPqOjlQ.js +1 -0
- package/storybook-static/assets/index-jrimW4QO.js +1 -0
- package/storybook-static/assets/index-nqc17SX4.js +1 -0
- package/storybook-static/assets/input-11YRd9gD.js +1 -0
- package/storybook-static/assets/jsx-runtime-D_zvdyIk.js +9 -0
- package/storybook-static/assets/label-Do8ODIVk.js +1 -0
- package/storybook-static/assets/lodash-DDwpuhPG.js +73 -0
- package/storybook-static/assets/matchers-7Z3WT2CE-T3xScrR7.js +14 -0
- package/storybook-static/assets/minimal-modern-BlYVzfQU.css +1 -0
- package/storybook-static/assets/popover-CcciSWAw.js +1 -0
- package/storybook-static/assets/preload-helper-Dp1pzeXC.js +1 -0
- package/storybook-static/assets/radio-group-DiJ0Y_KQ.js +1 -0
- package/storybook-static/assets/react-18-Cr9fq_Ip.js +25 -0
- package/storybook-static/assets/react-icons.esm-B_ULMmNU.js +1 -0
- package/storybook-static/assets/refresh-cw-BmRDhIV_.js +6 -0
- package/storybook-static/assets/schemas-CGNYCiJ6.js +18 -0
- package/storybook-static/assets/section-factories-DCCY9R35.js +1 -0
- package/storybook-static/assets/select-DDrkxaOg.js +6 -0
- package/storybook-static/assets/separator-o5SAUnaJ.js +1 -0
- package/storybook-static/assets/settings-2-xWGvvbG6.js +6 -0
- package/storybook-static/assets/sheet-C7jhU3XE.js +1 -0
- package/storybook-static/assets/shopping-cart-BFlrufvo.js +11 -0
- package/storybook-static/assets/sidebar-C8hU1Mxy.js +6 -0
- package/storybook-static/assets/skeleton-CjDnQs43.js +1 -0
- package/storybook-static/assets/spotify-CUDj7g8m.css +1 -0
- package/storybook-static/assets/switch-CKGRuk3u.js +1 -0
- package/storybook-static/assets/table-CP3vMqFn.js +1 -0
- package/storybook-static/assets/tabs-CopK2m3j.js +1 -0
- package/storybook-static/assets/textarea-Dw2vruMl.js +1 -0
- package/storybook-static/assets/toggle-DmHbWetf.js +16 -0
- package/storybook-static/assets/tooltip-_LqYEYFw.js +1 -0
- package/storybook-static/assets/trash-2-xdbApPby.js +11 -0
- package/storybook-static/assets/utils-D-KgF5mV.js +1 -0
- package/storybook-static/assets/x-B1a4fyWM.js +6 -0
- package/storybook-static/favicon-wrapper.svg +46 -0
- package/storybook-static/favicon.svg +1 -0
- package/storybook-static/iframe.html +687 -0
- package/storybook-static/index.d.ts +64 -0
- package/storybook-static/index.d.ts.map +1 -0
- package/storybook-static/index.html +166 -0
- package/storybook-static/index.json +1 -0
- package/storybook-static/kit/builder/data-table/components/DataTable.d.ts +37 -0
- package/storybook-static/kit/builder/data-table/components/DataTable.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts +8 -0
- package/storybook-static/kit/builder/data-table/components/DataTableColumnHeader.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts +6 -0
- package/storybook-static/kit/builder/data-table/components/DataTablePagination.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts +5 -0
- package/storybook-static/kit/builder/data-table/components/DataTableViewOptions.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/index.d.ts +7 -0
- package/storybook-static/kit/builder/data-table/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/types.d.ts +27 -0
- package/storybook-static/kit/builder/data-table/types.d.ts.map +1 -0
- package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts +2 -0
- package/storybook-static/kit/builder/data-table/utils/dotAccessor.d.ts.map +1 -0
- package/storybook-static/kit/builder/dialog/index.d.ts +3 -0
- package/storybook-static/kit/builder/dialog/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/dialog/provider.d.ts +26 -0
- package/storybook-static/kit/builder/dialog/provider.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/FormBuilder.d.ts +137 -0
- package/storybook-static/kit/builder/form/components/FormBuilder.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts +20 -0
- package/storybook-static/kit/builder/form/components/FormBuilderActions.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts +12 -0
- package/storybook-static/kit/builder/form/components/FormBuilderField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/ArrayField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/AutocompleteField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/CheckboxField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/DateField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/DateField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/FileField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/FileField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/NumberField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/ObjectField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/RadioField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/SelectField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/SwitchField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/TextField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/TextField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts +3 -0
- package/storybook-static/kit/builder/form/components/fields/TextareaField.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/index.d.ts +14 -0
- package/storybook-static/kit/builder/form/components/fields/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/fields/types.d.ts +14 -0
- package/storybook-static/kit/builder/form/components/fields/types.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/components/index.d.ts +4 -0
- package/storybook-static/kit/builder/form/components/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/index.d.ts +3 -0
- package/storybook-static/kit/builder/form/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/common-forms.d.ts +7 -0
- package/storybook-static/kit/builder/form/utils/common-forms.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/dependencies.d.ts +41 -0
- package/storybook-static/kit/builder/form/utils/dependencies.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/field-factories.d.ts +23 -0
- package/storybook-static/kit/builder/form/utils/field-factories.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/index.d.ts +15 -0
- package/storybook-static/kit/builder/form/utils/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/section-factories.d.ts +7 -0
- package/storybook-static/kit/builder/form/utils/section-factories.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/transformers.d.ts +6 -0
- package/storybook-static/kit/builder/form/utils/transformers.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/validations.d.ts +13 -0
- package/storybook-static/kit/builder/form/utils/validations.d.ts.map +1 -0
- package/storybook-static/kit/builder/form/utils/validators.d.ts +8 -0
- package/storybook-static/kit/builder/form/utils/validators.d.ts.map +1 -0
- package/storybook-static/kit/builder/page/Page.d.ts +48 -0
- package/storybook-static/kit/builder/page/Page.d.ts.map +1 -0
- package/storybook-static/kit/builder/page/index.d.ts +2 -0
- package/storybook-static/kit/builder/page/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/section/SectionBuilder.d.ts +3 -0
- package/storybook-static/kit/builder/section/SectionBuilder.d.ts.map +1 -0
- package/storybook-static/kit/builder/section/index.d.ts +3 -0
- package/storybook-static/kit/builder/section/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/section/types.d.ts +70 -0
- package/storybook-static/kit/builder/section/types.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/context.d.ts +3 -0
- package/storybook-static/kit/builder/stack-dialog/context.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/hooks.d.ts +6 -0
- package/storybook-static/kit/builder/stack-dialog/hooks.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/index.d.ts +5 -0
- package/storybook-static/kit/builder/stack-dialog/index.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/provider.d.ts +3 -0
- package/storybook-static/kit/builder/stack-dialog/provider.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/renderer.d.ts +6 -0
- package/storybook-static/kit/builder/stack-dialog/renderer.d.ts.map +1 -0
- package/storybook-static/kit/builder/stack-dialog/types.d.ts +20 -0
- package/storybook-static/kit/builder/stack-dialog/types.d.ts.map +1 -0
- package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts +53 -0
- package/storybook-static/kit/components/autocomplete/Autocomplete.d.ts.map +1 -0
- package/storybook-static/kit/components/autocomplete/index.d.ts +4 -0
- package/storybook-static/kit/components/autocomplete/index.d.ts.map +1 -0
- package/storybook-static/kit/components/autocomplete/types.d.ts +19 -0
- package/storybook-static/kit/components/autocomplete/types.d.ts.map +1 -0
- package/storybook-static/kit/components/login/Login.d.ts +29 -0
- package/storybook-static/kit/components/login/Login.d.ts.map +1 -0
- package/storybook-static/kit/components/login/index.d.ts +2 -0
- package/storybook-static/kit/components/login/index.d.ts.map +1 -0
- package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts +32 -0
- package/storybook-static/kit/components/monthpicker/MonthPicker.d.ts.map +1 -0
- package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts +48 -0
- package/storybook-static/kit/components/monthpicker/MonthRangePicker.d.ts.map +1 -0
- package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts +17 -0
- package/storybook-static/kit/layouts/admin/components/AdminLayout.d.ts.map +1 -0
- package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts +5 -0
- package/storybook-static/kit/layouts/admin/components/ThemeToggle.d.ts.map +1 -0
- package/storybook-static/kit/layouts/admin/hooks/menu.d.ts +13 -0
- package/storybook-static/kit/layouts/admin/hooks/menu.d.ts.map +1 -0
- package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts +7 -0
- package/storybook-static/kit/layouts/admin/providers/AdminMenuProvider.d.ts.map +1 -0
- package/storybook-static/kit/layouts/admin/types/index.d.ts +27 -0
- package/storybook-static/kit/layouts/admin/types/index.d.ts.map +1 -0
- package/storybook-static/kit/providers/ThemeProvider.d.ts +14 -0
- package/storybook-static/kit/providers/ThemeProvider.d.ts.map +1 -0
- package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/project.json +1 -0
- package/storybook-static/sb-addons/a11y-5/manager-bundle.js +5 -0
- package/storybook-static/sb-addons/essentials-backgrounds-1/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-measure-2/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-outline-3/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/interactions-4/manager-bundle.js +57 -0
- package/storybook-static/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +971 -0
- package/storybook-static/sb-addons/storysource-6/manager-bundle.js +3 -0
- package/storybook-static/sb-common-assets/favicon-wrapper.svg +46 -0
- package/storybook-static/sb-common-assets/favicon.svg +1 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/globals-module-info.js +797 -0
- package/storybook-static/sb-manager/globals-runtime.js +69653 -0
- package/storybook-static/sb-manager/globals.js +34 -0
- package/storybook-static/sb-manager/runtime.js +13181 -0
- package/storybook-static/shadcn/hooks/use-mobile.d.ts +2 -0
- package/storybook-static/shadcn/hooks/use-mobile.d.ts.map +1 -0
- package/storybook-static/shadcn/lib/utils.d.ts +3 -0
- package/storybook-static/shadcn/lib/utils.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/accordion.d.ts +8 -0
- package/storybook-static/shadcn/ui/accordion.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/alert-dialog.d.ts +15 -0
- package/storybook-static/shadcn/ui/alert-dialog.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/alert.d.ts +10 -0
- package/storybook-static/shadcn/ui/alert.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/aspect-ratio.d.ts +4 -0
- package/storybook-static/shadcn/ui/aspect-ratio.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/avatar.d.ts +7 -0
- package/storybook-static/shadcn/ui/avatar.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/badge.d.ts +10 -0
- package/storybook-static/shadcn/ui/badge.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/breadcrumb.d.ts +12 -0
- package/storybook-static/shadcn/ui/breadcrumb.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/button.d.ts +11 -0
- package/storybook-static/shadcn/ui/button.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/calendar.d.ts +9 -0
- package/storybook-static/shadcn/ui/calendar.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/card.d.ts +10 -0
- package/storybook-static/shadcn/ui/card.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/carousel.d.ts +20 -0
- package/storybook-static/shadcn/ui/carousel.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/chart.d.ts +41 -0
- package/storybook-static/shadcn/ui/chart.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/checkbox.d.ts +5 -0
- package/storybook-static/shadcn/ui/checkbox.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/collapsible.d.ts +6 -0
- package/storybook-static/shadcn/ui/collapsible.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/command.d.ts +19 -0
- package/storybook-static/shadcn/ui/command.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/context-menu.d.ts +26 -0
- package/storybook-static/shadcn/ui/context-menu.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/dialog.d.ts +16 -0
- package/storybook-static/shadcn/ui/dialog.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/drawer.d.ts +14 -0
- package/storybook-static/shadcn/ui/drawer.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/dropdown-menu.d.ts +26 -0
- package/storybook-static/shadcn/ui/dropdown-menu.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/form.d.ts +25 -0
- package/storybook-static/shadcn/ui/form.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/hover-card.d.ts +7 -0
- package/storybook-static/shadcn/ui/hover-card.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/input-otp.d.ts +12 -0
- package/storybook-static/shadcn/ui/input-otp.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/input.d.ts +4 -0
- package/storybook-static/shadcn/ui/input.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/label.d.ts +5 -0
- package/storybook-static/shadcn/ui/label.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/menubar.d.ts +27 -0
- package/storybook-static/shadcn/ui/menubar.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/navigation-menu.d.ts +15 -0
- package/storybook-static/shadcn/ui/navigation-menu.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/pagination.d.ts +14 -0
- package/storybook-static/shadcn/ui/pagination.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/popover.d.ts +8 -0
- package/storybook-static/shadcn/ui/popover.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/progress.d.ts +5 -0
- package/storybook-static/shadcn/ui/progress.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/radio-group.d.ts +6 -0
- package/storybook-static/shadcn/ui/radio-group.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/resizable.d.ts +9 -0
- package/storybook-static/shadcn/ui/resizable.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/scroll-area.d.ts +6 -0
- package/storybook-static/shadcn/ui/scroll-area.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/select.d.ts +16 -0
- package/storybook-static/shadcn/ui/select.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/separator.d.ts +5 -0
- package/storybook-static/shadcn/ui/separator.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/sheet.d.ts +14 -0
- package/storybook-static/shadcn/ui/sheet.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/sidebar.d.ts +70 -0
- package/storybook-static/shadcn/ui/sidebar.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/skeleton.d.ts +3 -0
- package/storybook-static/shadcn/ui/skeleton.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/slider.d.ts +5 -0
- package/storybook-static/shadcn/ui/slider.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/sonner.d.ts +4 -0
- package/storybook-static/shadcn/ui/sonner.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/switch.d.ts +5 -0
- package/storybook-static/shadcn/ui/switch.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/table.d.ts +11 -0
- package/storybook-static/shadcn/ui/table.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/tabs.d.ts +8 -0
- package/storybook-static/shadcn/ui/tabs.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/textarea.d.ts +4 -0
- package/storybook-static/shadcn/ui/textarea.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/toggle-group.d.ts +8 -0
- package/storybook-static/shadcn/ui/toggle-group.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/toggle.d.ts +10 -0
- package/storybook-static/shadcn/ui/toggle.d.ts.map +1 -0
- package/storybook-static/shadcn/ui/tooltip.d.ts +8 -0
- package/storybook-static/shadcn/ui/tooltip.d.ts.map +1 -0
- package/storybook-static/vite-inject-mocker-entry.js +18 -0
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Delete, ArrowLeft, CornerDownLeft } from "lucide-react";
|
|
5
|
+
import { cn } from "../../../shadcn/lib/utils";
|
|
6
|
+
import { Button } from "../../../shadcn/ui/button";
|
|
7
|
+
|
|
8
|
+
// Constants
|
|
9
|
+
const KEY_BUTTON_BASE_CLASSES =
|
|
10
|
+
"rounded-xl border-2 border-teal-200 bg-white text-teal-600 transition-all duration-150 hover:bg-teal-50 h-16 min-w-[80px] max-w-[88px] text-lg font-semibold";
|
|
11
|
+
const KEY_BUTTON_COMPACT_CLASSES =
|
|
12
|
+
"rounded-xl border-2 border-teal-200 bg-white text-teal-600 transition-all duration-150 hover:bg-teal-50 h-16 min-w-[80px] max-w-[80px] text-lg font-semibold";
|
|
13
|
+
const BACKSPACE_BUTTON_CLASSES =
|
|
14
|
+
"rounded-xl bg-red-600 text-white transition-all duration-150 hover:bg-red-700 h-16 min-w-[80px] max-w-[80px]";
|
|
15
|
+
const SPACE_BUTTON_CLASSES =
|
|
16
|
+
"rounded-xl border-2 border-teal-200 bg-white text-teal-600 transition-all duration-150 hover:bg-teal-50 h-16 min-w-[630px] max-w-[630px] flex-1 text-lg font-semibold";
|
|
17
|
+
const ENTER_BUTTON_CLASSES =
|
|
18
|
+
"rounded-xl border-2 border-teal-200 bg-green-500 text-white transition-all duration-150 hover:bg-green-600 h-16 min-w-[80px] max-w-[80px] text-lg font-semibold";
|
|
19
|
+
const PRESSED_KEY_CLASSES = "bg-teal-100 border-teal-400 scale-95";
|
|
20
|
+
const ACTIVE_TOGGLE_CLASSES =
|
|
21
|
+
"bg-teal-600 text-white border-teal-600 hover:bg-teal-700";
|
|
22
|
+
|
|
23
|
+
export type KeyboardLayout = "qwerty" | "qwertz" | "azerty";
|
|
24
|
+
|
|
25
|
+
export interface KeyboardProps
|
|
26
|
+
extends Omit<
|
|
27
|
+
React.HTMLAttributes<HTMLDivElement>,
|
|
28
|
+
"onChange" | "onKeyPress"
|
|
29
|
+
> {
|
|
30
|
+
value?: string;
|
|
31
|
+
onChange?: (value: string) => void;
|
|
32
|
+
onKeyPress?: (key: string) => void;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
layout?: KeyboardLayout;
|
|
35
|
+
showNumbers?: boolean;
|
|
36
|
+
showSymbols?: boolean;
|
|
37
|
+
showShift?: boolean;
|
|
38
|
+
showSpace?: boolean;
|
|
39
|
+
showBackspace?: boolean;
|
|
40
|
+
showEnter?: boolean;
|
|
41
|
+
className?: string;
|
|
42
|
+
buttonClassName?: string;
|
|
43
|
+
customKeyStyle?: React.CSSProperties;
|
|
44
|
+
customKeyClassName?: string;
|
|
45
|
+
capsLock?: boolean;
|
|
46
|
+
onCapsLockChange?: (capsLock: boolean) => void;
|
|
47
|
+
inputRef?: React.RefObject<HTMLInputElement | HTMLTextAreaElement | null>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const QWERTY_LAYOUT = {
|
|
51
|
+
row1: ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
|
|
52
|
+
row2: ["a", "s", "d", "f", "g", "h", "j", "k", "l"],
|
|
53
|
+
row3: ["z", "x", "c", "v", "b", "n", "m"],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const QWERTZ_LAYOUT = {
|
|
57
|
+
row1: ["q", "w", "e", "r", "t", "z", "u", "i", "o", "p"],
|
|
58
|
+
row2: ["a", "s", "d", "f", "g", "h", "j", "k", "l"],
|
|
59
|
+
row3: ["y", "x", "c", "v", "b", "n", "m"],
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const AZERTY_LAYOUT = {
|
|
63
|
+
row1: ["a", "z", "e", "r", "t", "y", "u", "i", "o", "p"],
|
|
64
|
+
row2: ["q", "s", "d", "f", "g", "h", "j", "k", "l", "m"],
|
|
65
|
+
row3: ["w", "x", "c", "v", "b", "n"],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const NUMBER_ROW = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
|
|
69
|
+
|
|
70
|
+
const getLayout = (layout: KeyboardLayout) => {
|
|
71
|
+
switch (layout) {
|
|
72
|
+
case "qwertz":
|
|
73
|
+
return QWERTZ_LAYOUT;
|
|
74
|
+
case "azerty":
|
|
75
|
+
return AZERTY_LAYOUT;
|
|
76
|
+
default:
|
|
77
|
+
return QWERTY_LAYOUT;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export function Keyboard({
|
|
82
|
+
value: controlledValue,
|
|
83
|
+
onChange,
|
|
84
|
+
onKeyPress,
|
|
85
|
+
disabled = false,
|
|
86
|
+
layout = "qwerty",
|
|
87
|
+
showNumbers = true,
|
|
88
|
+
showSymbols = true,
|
|
89
|
+
showShift = true,
|
|
90
|
+
showSpace = true,
|
|
91
|
+
showBackspace = true,
|
|
92
|
+
showEnter = false,
|
|
93
|
+
className,
|
|
94
|
+
buttonClassName,
|
|
95
|
+
customKeyStyle,
|
|
96
|
+
customKeyClassName,
|
|
97
|
+
capsLock: controlledCapsLock,
|
|
98
|
+
onCapsLockChange,
|
|
99
|
+
inputRef,
|
|
100
|
+
...props
|
|
101
|
+
}: KeyboardProps) {
|
|
102
|
+
const [internalValue, setInternalValue] = React.useState("");
|
|
103
|
+
const [internalCapsLock, setInternalCapsLock] = React.useState(false);
|
|
104
|
+
const [shiftPressed, setShiftPressed] = React.useState(false);
|
|
105
|
+
const [symbolMode, setSymbolMode] = React.useState(false);
|
|
106
|
+
const [pressedKey, setPressedKey] = React.useState<string | null>(null);
|
|
107
|
+
const [inputValue, setInputValue] = React.useState("");
|
|
108
|
+
const pendingCursorPos = React.useRef<number | null>(null);
|
|
109
|
+
|
|
110
|
+
// Use a ref to track if virtual Caps Lock was just clicked (to prevent sync override)
|
|
111
|
+
const virtualCapsLockJustToggled = React.useRef(false);
|
|
112
|
+
// Track the last known Caps Lock state to detect changes
|
|
113
|
+
const lastKnownCapsLockState = React.useRef(false);
|
|
114
|
+
|
|
115
|
+
const isControlled = controlledValue !== undefined;
|
|
116
|
+
const value = isControlled ? controlledValue : internalValue;
|
|
117
|
+
|
|
118
|
+
// Sync inputValue with actual input value when inputRef is provided
|
|
119
|
+
React.useEffect(() => {
|
|
120
|
+
if (inputRef?.current) {
|
|
121
|
+
const updateInputValue = () => {
|
|
122
|
+
setInputValue(inputRef.current?.value ?? "");
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Initial sync
|
|
126
|
+
updateInputValue();
|
|
127
|
+
|
|
128
|
+
// Listen to input events to keep in sync
|
|
129
|
+
const input = inputRef.current;
|
|
130
|
+
input.addEventListener("input", updateInputValue);
|
|
131
|
+
input.addEventListener("change", updateInputValue);
|
|
132
|
+
|
|
133
|
+
return () => {
|
|
134
|
+
input.removeEventListener("input", updateInputValue);
|
|
135
|
+
input.removeEventListener("change", updateInputValue);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
setInputValue(value);
|
|
139
|
+
return undefined;
|
|
140
|
+
}, [inputRef, value]);
|
|
141
|
+
|
|
142
|
+
// Restore cursor position after React re-renders
|
|
143
|
+
React.useEffect(() => {
|
|
144
|
+
if (inputRef?.current && pendingCursorPos.current !== null) {
|
|
145
|
+
const pos = pendingCursorPos.current;
|
|
146
|
+
pendingCursorPos.current = null;
|
|
147
|
+
// Use setTimeout to ensure React has finished rendering
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
if (inputRef?.current) {
|
|
150
|
+
inputRef.current.setSelectionRange(pos, pos);
|
|
151
|
+
}
|
|
152
|
+
}, 0);
|
|
153
|
+
}
|
|
154
|
+
}, [value, inputRef]);
|
|
155
|
+
|
|
156
|
+
// Get the actual input value for disabled checks
|
|
157
|
+
const actualInputValue = inputRef?.current ? inputValue : value;
|
|
158
|
+
|
|
159
|
+
const isCapsLockControlled = controlledCapsLock !== undefined;
|
|
160
|
+
const capsLock = isCapsLockControlled ? controlledCapsLock : internalCapsLock;
|
|
161
|
+
|
|
162
|
+
// Update ref when capsLock changes
|
|
163
|
+
React.useEffect(() => {
|
|
164
|
+
lastKnownCapsLockState.current = capsLock;
|
|
165
|
+
}, [capsLock]);
|
|
166
|
+
|
|
167
|
+
const keyboardLayout = React.useMemo(() => getLayout(layout), [layout]);
|
|
168
|
+
|
|
169
|
+
const isShiftActive = capsLock || shiftPressed;
|
|
170
|
+
|
|
171
|
+
// Map real keyboard keys to virtual keyboard keys
|
|
172
|
+
const mapRealKeyToVirtual = React.useCallback(
|
|
173
|
+
(key: string, event: KeyboardEvent): string | null => {
|
|
174
|
+
const keyLower = key.toLowerCase();
|
|
175
|
+
|
|
176
|
+
// Handle special keys
|
|
177
|
+
if (key === "Backspace" || key === "Delete") return "Backspace";
|
|
178
|
+
if (key === "Enter") return "Enter";
|
|
179
|
+
if (key === " ") return "Space";
|
|
180
|
+
if (key === "Tab") return "Tab";
|
|
181
|
+
if (key === "Shift" || key === "ShiftLeft" || key === "ShiftRight")
|
|
182
|
+
return "Shift";
|
|
183
|
+
if (key === "CapsLock") return "CapsLock";
|
|
184
|
+
if (key === "#" || key === "+" || key === "=") return "#+=";
|
|
185
|
+
|
|
186
|
+
// Handle numbers
|
|
187
|
+
if (/^[0-9]$/.test(key)) {
|
|
188
|
+
return symbolMode ? null : key;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Handle letters
|
|
192
|
+
if (/^[a-z]$/i.test(key)) {
|
|
193
|
+
if (symbolMode) {
|
|
194
|
+
// In symbol mode, letters map to symbols
|
|
195
|
+
return null; // Symbols are shown in dedicated rows
|
|
196
|
+
}
|
|
197
|
+
return keyLower;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Handle symbols when shift is pressed
|
|
201
|
+
if (event.shiftKey) {
|
|
202
|
+
const shiftSymbolMap: Record<string, string> = {
|
|
203
|
+
"1": ".",
|
|
204
|
+
"2": "@",
|
|
205
|
+
"3": "#",
|
|
206
|
+
"4": "_",
|
|
207
|
+
"5": "%",
|
|
208
|
+
"6": "^",
|
|
209
|
+
"7": "&",
|
|
210
|
+
"8": "*",
|
|
211
|
+
"9": "(",
|
|
212
|
+
"0": ")",
|
|
213
|
+
"-": ",",
|
|
214
|
+
"=": "+",
|
|
215
|
+
"[": "{",
|
|
216
|
+
"]": "}",
|
|
217
|
+
"\\": "|",
|
|
218
|
+
";": ":",
|
|
219
|
+
"'": '"',
|
|
220
|
+
",": "<",
|
|
221
|
+
".": ">",
|
|
222
|
+
"/": "?",
|
|
223
|
+
"`": "~",
|
|
224
|
+
};
|
|
225
|
+
return shiftSymbolMap[key] || null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Handle regular symbols
|
|
229
|
+
const symbolMap: Record<string, string> = {
|
|
230
|
+
"-": "-",
|
|
231
|
+
"=": "=",
|
|
232
|
+
"[": "[",
|
|
233
|
+
"]": "]",
|
|
234
|
+
"\\": "\\",
|
|
235
|
+
";": ";",
|
|
236
|
+
"'": "'",
|
|
237
|
+
",": ",",
|
|
238
|
+
".": ".",
|
|
239
|
+
"/": "/",
|
|
240
|
+
"`": "`",
|
|
241
|
+
};
|
|
242
|
+
return symbolMap[key] || null;
|
|
243
|
+
},
|
|
244
|
+
[symbolMode],
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const handleKeyPress = React.useCallback(
|
|
248
|
+
(key: string) => {
|
|
249
|
+
if (disabled) return;
|
|
250
|
+
|
|
251
|
+
// If inputRef is provided, manipulate the input directly to handle selection
|
|
252
|
+
if (inputRef?.current) {
|
|
253
|
+
const input = inputRef.current;
|
|
254
|
+
const start = input.selectionStart ?? 0;
|
|
255
|
+
const end = input.selectionEnd ?? 0;
|
|
256
|
+
const currentValue = input.value;
|
|
257
|
+
|
|
258
|
+
// Replace selected text with the new key
|
|
259
|
+
const newValue =
|
|
260
|
+
currentValue.slice(0, start) + key + currentValue.slice(end);
|
|
261
|
+
const newCursorPos = start + key.length;
|
|
262
|
+
|
|
263
|
+
// Update our internal state first
|
|
264
|
+
setInputValue(newValue);
|
|
265
|
+
|
|
266
|
+
// Store cursor position to restore after React re-renders
|
|
267
|
+
pendingCursorPos.current = newCursorPos;
|
|
268
|
+
|
|
269
|
+
// Call onChange to update parent state - React will handle the re-render
|
|
270
|
+
onChange?.(newValue);
|
|
271
|
+
if (!isControlled) {
|
|
272
|
+
setInternalValue(newValue);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
onKeyPress?.(key);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Fallback to old behavior if no inputRef
|
|
280
|
+
const newValue = value + key;
|
|
281
|
+
if (isControlled) {
|
|
282
|
+
onChange?.(newValue);
|
|
283
|
+
} else {
|
|
284
|
+
setInternalValue(newValue);
|
|
285
|
+
onChange?.(newValue);
|
|
286
|
+
}
|
|
287
|
+
onKeyPress?.(key);
|
|
288
|
+
},
|
|
289
|
+
[disabled, value, isControlled, onChange, onKeyPress, inputRef],
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const handleBackspace = React.useCallback(() => {
|
|
293
|
+
if (disabled) return;
|
|
294
|
+
|
|
295
|
+
// If inputRef is provided, check the actual input value
|
|
296
|
+
if (inputRef?.current) {
|
|
297
|
+
const input = inputRef.current;
|
|
298
|
+
const start = input.selectionStart ?? 0;
|
|
299
|
+
const end = input.selectionEnd ?? 0;
|
|
300
|
+
const currentValue = input.value;
|
|
301
|
+
|
|
302
|
+
if (start === end && start === 0) return; // Nothing to delete
|
|
303
|
+
|
|
304
|
+
// Set pressed key for animation
|
|
305
|
+
setPressedKey("Backspace");
|
|
306
|
+
setTimeout(() => {
|
|
307
|
+
setPressedKey(null);
|
|
308
|
+
}, 150);
|
|
309
|
+
|
|
310
|
+
// If text is selected, delete the selection
|
|
311
|
+
// Otherwise, delete the character before the cursor
|
|
312
|
+
let newValue: string;
|
|
313
|
+
let newCursorPos: number;
|
|
314
|
+
|
|
315
|
+
if (start !== end) {
|
|
316
|
+
// Delete selected text
|
|
317
|
+
newValue = currentValue.slice(0, start) + currentValue.slice(end);
|
|
318
|
+
newCursorPos = start;
|
|
319
|
+
} else {
|
|
320
|
+
// Delete character before cursor
|
|
321
|
+
newValue = currentValue.slice(0, start - 1) + currentValue.slice(start);
|
|
322
|
+
newCursorPos = Math.max(0, start - 1);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Update our internal state first
|
|
326
|
+
setInputValue(newValue);
|
|
327
|
+
|
|
328
|
+
// Store cursor position to restore after React re-renders
|
|
329
|
+
pendingCursorPos.current = newCursorPos;
|
|
330
|
+
|
|
331
|
+
// Call onChange to update parent state - React will handle the re-render
|
|
332
|
+
onChange?.(newValue);
|
|
333
|
+
if (!isControlled) {
|
|
334
|
+
setInternalValue(newValue);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
onKeyPress?.("Backspace");
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Fallback to old behavior if no inputRef
|
|
342
|
+
if (value.length === 0) return;
|
|
343
|
+
|
|
344
|
+
// Set pressed key for animation
|
|
345
|
+
setPressedKey("Backspace");
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
setPressedKey(null);
|
|
348
|
+
}, 150);
|
|
349
|
+
|
|
350
|
+
const newValue = value.slice(0, -1);
|
|
351
|
+
if (isControlled) {
|
|
352
|
+
onChange?.(newValue);
|
|
353
|
+
} else {
|
|
354
|
+
setInternalValue(newValue);
|
|
355
|
+
onChange?.(newValue);
|
|
356
|
+
}
|
|
357
|
+
onKeyPress?.("Backspace");
|
|
358
|
+
}, [disabled, value, isControlled, onChange, onKeyPress, inputRef]);
|
|
359
|
+
|
|
360
|
+
const handleSpace = React.useCallback(() => {
|
|
361
|
+
// Set pressed key for animation
|
|
362
|
+
setPressedKey("Space");
|
|
363
|
+
setTimeout(() => {
|
|
364
|
+
setPressedKey(null);
|
|
365
|
+
}, 150);
|
|
366
|
+
handleKeyPress(" ");
|
|
367
|
+
}, [handleKeyPress]);
|
|
368
|
+
|
|
369
|
+
const handleEnter = React.useCallback(() => {
|
|
370
|
+
if (disabled) return;
|
|
371
|
+
|
|
372
|
+
// Set pressed key for animation
|
|
373
|
+
setPressedKey("Enter");
|
|
374
|
+
setTimeout(() => {
|
|
375
|
+
setPressedKey(null);
|
|
376
|
+
}, 150);
|
|
377
|
+
|
|
378
|
+
// If inputRef is provided, handle Enter like a real keyboard
|
|
379
|
+
if (inputRef?.current) {
|
|
380
|
+
const input = inputRef?.current;
|
|
381
|
+
const isTextarea = input.tagName === "TEXTAREA";
|
|
382
|
+
const isInput = input.tagName === "INPUT";
|
|
383
|
+
|
|
384
|
+
if (isTextarea) {
|
|
385
|
+
// For textarea: insert newline like real keyboard
|
|
386
|
+
const start = input.selectionStart ?? 0;
|
|
387
|
+
const end = input.selectionEnd ?? 0;
|
|
388
|
+
const currentValue = input.value;
|
|
389
|
+
|
|
390
|
+
// Replace selected text with newline, or insert newline at cursor
|
|
391
|
+
const newValue =
|
|
392
|
+
currentValue.slice(0, start) + "\n" + currentValue.slice(end);
|
|
393
|
+
const newCursorPos = start + 1;
|
|
394
|
+
|
|
395
|
+
// Update input value
|
|
396
|
+
input.value = newValue;
|
|
397
|
+
|
|
398
|
+
// Set cursor position
|
|
399
|
+
input.setSelectionRange(newCursorPos, newCursorPos);
|
|
400
|
+
|
|
401
|
+
// Trigger input event for React
|
|
402
|
+
const inputEvent = new Event("input", { bubbles: true });
|
|
403
|
+
input.dispatchEvent(inputEvent);
|
|
404
|
+
|
|
405
|
+
// Update controlled/uncontrolled state
|
|
406
|
+
if (isControlled) {
|
|
407
|
+
onChange?.(newValue);
|
|
408
|
+
} else {
|
|
409
|
+
setInternalValue(newValue);
|
|
410
|
+
onChange?.(newValue);
|
|
411
|
+
}
|
|
412
|
+
} else if (isInput) {
|
|
413
|
+
// For input: trigger Enter key events like real keyboard
|
|
414
|
+
// This will trigger form submission if inside a form
|
|
415
|
+
|
|
416
|
+
// Create and dispatch keydown event
|
|
417
|
+
const keyDownEvent = new KeyboardEvent("keydown", {
|
|
418
|
+
key: "Enter",
|
|
419
|
+
code: "Enter",
|
|
420
|
+
keyCode: 13,
|
|
421
|
+
which: 13,
|
|
422
|
+
bubbles: true,
|
|
423
|
+
cancelable: true,
|
|
424
|
+
});
|
|
425
|
+
input.dispatchEvent(keyDownEvent);
|
|
426
|
+
|
|
427
|
+
// Only trigger keypress and keyup if keydown wasn't prevented
|
|
428
|
+
if (!keyDownEvent.defaultPrevented) {
|
|
429
|
+
// Create and dispatch keypress event
|
|
430
|
+
const keyPressEvent = new KeyboardEvent("keypress", {
|
|
431
|
+
key: "Enter",
|
|
432
|
+
code: "Enter",
|
|
433
|
+
keyCode: 13,
|
|
434
|
+
which: 13,
|
|
435
|
+
bubbles: true,
|
|
436
|
+
cancelable: true,
|
|
437
|
+
});
|
|
438
|
+
input.dispatchEvent(keyPressEvent);
|
|
439
|
+
|
|
440
|
+
// Create and dispatch keyup event
|
|
441
|
+
const keyUpEvent = new KeyboardEvent("keyup", {
|
|
442
|
+
key: "Enter",
|
|
443
|
+
code: "Enter",
|
|
444
|
+
keyCode: 13,
|
|
445
|
+
which: 13,
|
|
446
|
+
bubbles: true,
|
|
447
|
+
cancelable: true,
|
|
448
|
+
});
|
|
449
|
+
input.dispatchEvent(keyUpEvent);
|
|
450
|
+
|
|
451
|
+
// If input is inside a form, trigger form submit
|
|
452
|
+
const form = input.closest("form");
|
|
453
|
+
if (form && !keyPressEvent.defaultPrevented) {
|
|
454
|
+
// Trigger form submit event
|
|
455
|
+
const submitEvent = new Event("submit", {
|
|
456
|
+
bubbles: true,
|
|
457
|
+
cancelable: true,
|
|
458
|
+
});
|
|
459
|
+
form.dispatchEvent(submitEvent);
|
|
460
|
+
|
|
461
|
+
// If submit wasn't prevented, actually submit the form
|
|
462
|
+
if (!submitEvent.defaultPrevented) {
|
|
463
|
+
form.requestSubmit();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Call onKeyPress callback
|
|
470
|
+
onKeyPress?.("Enter");
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Fallback: if no inputRef, just add newline to value
|
|
475
|
+
const newValue = value + "\n";
|
|
476
|
+
if (isControlled) {
|
|
477
|
+
onChange?.(newValue);
|
|
478
|
+
} else {
|
|
479
|
+
setInternalValue(newValue);
|
|
480
|
+
onChange?.(newValue);
|
|
481
|
+
}
|
|
482
|
+
onKeyPress?.("Enter");
|
|
483
|
+
}, [disabled, value, isControlled, onChange, onKeyPress, inputRef]);
|
|
484
|
+
|
|
485
|
+
const toggleCapsLock = React.useCallback(() => {
|
|
486
|
+
// Set pressed key for animation
|
|
487
|
+
setPressedKey("CapsLock");
|
|
488
|
+
setTimeout(() => {
|
|
489
|
+
setPressedKey(null);
|
|
490
|
+
}, 150);
|
|
491
|
+
|
|
492
|
+
// Set flag to prevent sync from overriding our toggle for a short period
|
|
493
|
+
virtualCapsLockJustToggled.current = true;
|
|
494
|
+
|
|
495
|
+
// Always use functional update to get the latest state
|
|
496
|
+
if (isCapsLockControlled) {
|
|
497
|
+
// For controlled components, use the current prop value
|
|
498
|
+
const currentCapsLock = controlledCapsLock ?? false;
|
|
499
|
+
const newCapsLock = !currentCapsLock;
|
|
500
|
+
lastKnownCapsLockState.current = newCapsLock;
|
|
501
|
+
onCapsLockChange?.(newCapsLock);
|
|
502
|
+
} else {
|
|
503
|
+
// For uncontrolled components, use functional update to avoid stale closures
|
|
504
|
+
setInternalCapsLock((prev) => {
|
|
505
|
+
const newCapsLock = !prev;
|
|
506
|
+
lastKnownCapsLockState.current = newCapsLock;
|
|
507
|
+
onCapsLockChange?.(newCapsLock);
|
|
508
|
+
return newCapsLock;
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// Reset flag after a delay to allow sync again
|
|
513
|
+
setTimeout(() => {
|
|
514
|
+
virtualCapsLockJustToggled.current = false;
|
|
515
|
+
}, 200);
|
|
516
|
+
}, [isCapsLockControlled, onCapsLockChange, controlledCapsLock]);
|
|
517
|
+
|
|
518
|
+
const toggleSymbolMode = React.useCallback(() => {
|
|
519
|
+
// Set pressed key for animation
|
|
520
|
+
setPressedKey("#+=");
|
|
521
|
+
setTimeout(() => {
|
|
522
|
+
setPressedKey(null);
|
|
523
|
+
}, 150);
|
|
524
|
+
setSymbolMode((prev) => !prev);
|
|
525
|
+
}, []);
|
|
526
|
+
|
|
527
|
+
// Listen to real keyboard events and sync Caps Lock state
|
|
528
|
+
React.useEffect(() => {
|
|
529
|
+
if (disabled) return;
|
|
530
|
+
|
|
531
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
532
|
+
// Handle Caps Lock key press on physical keyboard
|
|
533
|
+
if (event.key === "CapsLock" || event.key === "Caps") {
|
|
534
|
+
setPressedKey("CapsLock");
|
|
535
|
+
virtualCapsLockJustToggled.current = false; // Reset flag - physical keyboard takes priority
|
|
536
|
+
|
|
537
|
+
// When Caps Lock is pressed, the state changes AFTER this event
|
|
538
|
+
// So we toggle based on the last known state
|
|
539
|
+
const newCapsLock = !lastKnownCapsLockState.current;
|
|
540
|
+
lastKnownCapsLockState.current = newCapsLock;
|
|
541
|
+
|
|
542
|
+
if (!isCapsLockControlled) {
|
|
543
|
+
setInternalCapsLock(newCapsLock);
|
|
544
|
+
onCapsLockChange?.(newCapsLock);
|
|
545
|
+
} else {
|
|
546
|
+
onCapsLockChange?.(newCapsLock);
|
|
547
|
+
}
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// Sync with browser's actual caps lock state on any key press
|
|
552
|
+
// This ensures we stay in sync with physical keyboard
|
|
553
|
+
// But skip if virtual Caps Lock was just toggled (to prevent override)
|
|
554
|
+
if (!virtualCapsLockJustToggled.current) {
|
|
555
|
+
const browserCapsLock = event.getModifierState("CapsLock");
|
|
556
|
+
|
|
557
|
+
// Only update if state has actually changed
|
|
558
|
+
if (browserCapsLock !== lastKnownCapsLockState.current) {
|
|
559
|
+
lastKnownCapsLockState.current = browserCapsLock;
|
|
560
|
+
|
|
561
|
+
if (!isCapsLockControlled) {
|
|
562
|
+
setInternalCapsLock(browserCapsLock);
|
|
563
|
+
onCapsLockChange?.(browserCapsLock);
|
|
564
|
+
} else {
|
|
565
|
+
onCapsLockChange?.(browserCapsLock);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const virtualKey = mapRealKeyToVirtual(event.key, event);
|
|
571
|
+
if (virtualKey) {
|
|
572
|
+
setPressedKey(virtualKey);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const handleKeyUp = (event: KeyboardEvent) => {
|
|
577
|
+
setPressedKey(null);
|
|
578
|
+
|
|
579
|
+
// Also check Caps Lock state on keyup to catch any changes
|
|
580
|
+
if (!virtualCapsLockJustToggled.current) {
|
|
581
|
+
const browserCapsLock = event.getModifierState("CapsLock");
|
|
582
|
+
if (browserCapsLock !== lastKnownCapsLockState.current) {
|
|
583
|
+
lastKnownCapsLockState.current = browserCapsLock;
|
|
584
|
+
|
|
585
|
+
if (!isCapsLockControlled) {
|
|
586
|
+
setInternalCapsLock(browserCapsLock);
|
|
587
|
+
onCapsLockChange?.(browserCapsLock);
|
|
588
|
+
} else {
|
|
589
|
+
onCapsLockChange?.(browserCapsLock);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
596
|
+
window.addEventListener("keyup", handleKeyUp);
|
|
597
|
+
|
|
598
|
+
return () => {
|
|
599
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
600
|
+
window.removeEventListener("keyup", handleKeyUp);
|
|
601
|
+
};
|
|
602
|
+
}, [disabled, mapRealKeyToVirtual, isCapsLockControlled, onCapsLockChange]);
|
|
603
|
+
|
|
604
|
+
// Helper to animate key press
|
|
605
|
+
const animateKeyPress = React.useCallback((key: string) => {
|
|
606
|
+
setPressedKey(key);
|
|
607
|
+
setTimeout(() => setPressedKey(null), 150);
|
|
608
|
+
}, []);
|
|
609
|
+
|
|
610
|
+
const formatKey = (key: string): string => {
|
|
611
|
+
if (symbolMode) {
|
|
612
|
+
const symbolMap: Record<string, string> = {
|
|
613
|
+
q: "[",
|
|
614
|
+
w: "]",
|
|
615
|
+
e: "\\",
|
|
616
|
+
r: ";",
|
|
617
|
+
t: "'",
|
|
618
|
+
y: ",",
|
|
619
|
+
u: ".",
|
|
620
|
+
i: "/",
|
|
621
|
+
o: "=",
|
|
622
|
+
p: "-",
|
|
623
|
+
a: "{",
|
|
624
|
+
s: "}",
|
|
625
|
+
d: ":",
|
|
626
|
+
f: '"',
|
|
627
|
+
g: "<",
|
|
628
|
+
h: ">",
|
|
629
|
+
j: "?",
|
|
630
|
+
k: "+",
|
|
631
|
+
l: "_",
|
|
632
|
+
z: "|",
|
|
633
|
+
x: "~",
|
|
634
|
+
c: "`",
|
|
635
|
+
v: "|",
|
|
636
|
+
b: "~",
|
|
637
|
+
n: "`",
|
|
638
|
+
m: "|",
|
|
639
|
+
};
|
|
640
|
+
return symbolMap[key.toLowerCase()] || key;
|
|
641
|
+
}
|
|
642
|
+
return isShiftActive ? key.toUpperCase() : key.toLowerCase();
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
const getNumberSymbol = (num: string, shift: boolean): string => {
|
|
646
|
+
if (!shift) return num;
|
|
647
|
+
const symbols: Record<string, string> = {
|
|
648
|
+
"1": ".",
|
|
649
|
+
"2": "@",
|
|
650
|
+
"3": "#",
|
|
651
|
+
"4": "_",
|
|
652
|
+
"5": "%",
|
|
653
|
+
"6": "^",
|
|
654
|
+
"7": "&",
|
|
655
|
+
"8": "*",
|
|
656
|
+
"9": "(",
|
|
657
|
+
"0": ")",
|
|
658
|
+
};
|
|
659
|
+
return symbols[num] || num;
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// Helper component for key buttons
|
|
663
|
+
const KeyButton = React.useCallback(
|
|
664
|
+
({
|
|
665
|
+
children,
|
|
666
|
+
onClick,
|
|
667
|
+
isPressed = false,
|
|
668
|
+
className = "",
|
|
669
|
+
compact = false,
|
|
670
|
+
}: {
|
|
671
|
+
children: React.ReactNode;
|
|
672
|
+
onClick: () => void;
|
|
673
|
+
isPressed?: boolean;
|
|
674
|
+
className?: string;
|
|
675
|
+
compact?: boolean;
|
|
676
|
+
}) => (
|
|
677
|
+
<Button
|
|
678
|
+
type="button"
|
|
679
|
+
disabled={disabled}
|
|
680
|
+
onClick={onClick}
|
|
681
|
+
style={customKeyStyle}
|
|
682
|
+
className={cn(
|
|
683
|
+
compact ? KEY_BUTTON_COMPACT_CLASSES : KEY_BUTTON_BASE_CLASSES,
|
|
684
|
+
isPressed && PRESSED_KEY_CLASSES,
|
|
685
|
+
buttonClassName,
|
|
686
|
+
customKeyClassName,
|
|
687
|
+
className
|
|
688
|
+
)}
|
|
689
|
+
>
|
|
690
|
+
{children}
|
|
691
|
+
</Button>
|
|
692
|
+
),
|
|
693
|
+
[disabled, customKeyStyle, buttonClassName, customKeyClassName]
|
|
694
|
+
);
|
|
695
|
+
|
|
696
|
+
// Helper component for symbol buttons
|
|
697
|
+
const SymbolButton = React.useCallback(
|
|
698
|
+
({ sym }: { sym: string }) => {
|
|
699
|
+
const isPressed = pressedKey === sym;
|
|
700
|
+
return (
|
|
701
|
+
<KeyButton
|
|
702
|
+
isPressed={isPressed}
|
|
703
|
+
onClick={() => {
|
|
704
|
+
animateKeyPress(sym);
|
|
705
|
+
handleKeyPress(sym);
|
|
706
|
+
}}
|
|
707
|
+
>
|
|
708
|
+
{sym}
|
|
709
|
+
</KeyButton>
|
|
710
|
+
);
|
|
711
|
+
},
|
|
712
|
+
[pressedKey, animateKeyPress, handleKeyPress, KeyButton]
|
|
713
|
+
);
|
|
714
|
+
|
|
715
|
+
// Helper component for letter buttons
|
|
716
|
+
const LetterButton = React.useCallback(
|
|
717
|
+
({ keyChar }: { keyChar: string }) => {
|
|
718
|
+
const displayChar = formatKey(keyChar);
|
|
719
|
+
const isPressed = pressedKey === keyChar.toLowerCase();
|
|
720
|
+
return (
|
|
721
|
+
<KeyButton
|
|
722
|
+
isPressed={isPressed}
|
|
723
|
+
onClick={() => {
|
|
724
|
+
animateKeyPress(keyChar.toLowerCase());
|
|
725
|
+
handleKeyPress(displayChar);
|
|
726
|
+
if (shiftPressed) setShiftPressed(false);
|
|
727
|
+
}}
|
|
728
|
+
>
|
|
729
|
+
{displayChar}
|
|
730
|
+
</KeyButton>
|
|
731
|
+
);
|
|
732
|
+
},
|
|
733
|
+
[
|
|
734
|
+
pressedKey,
|
|
735
|
+
shiftPressed,
|
|
736
|
+
animateKeyPress,
|
|
737
|
+
handleKeyPress,
|
|
738
|
+
formatKey,
|
|
739
|
+
KeyButton,
|
|
740
|
+
]
|
|
741
|
+
);
|
|
742
|
+
|
|
743
|
+
return (
|
|
744
|
+
<div
|
|
745
|
+
className={cn(
|
|
746
|
+
"flex flex-col gap-3 p-6 bg-background border border-border rounded-lg shadow-sm",
|
|
747
|
+
className,
|
|
748
|
+
)}
|
|
749
|
+
{...props}
|
|
750
|
+
>
|
|
751
|
+
{/* Number row - hidden when symbol mode is active */}
|
|
752
|
+
{showNumbers && (
|
|
753
|
+
<div className="flex gap-3 justify-center">
|
|
754
|
+
{NUMBER_ROW.map((num) => {
|
|
755
|
+
const displayChar = shiftPressed ? getNumberSymbol(num, true) : num;
|
|
756
|
+
const isPressed = pressedKey === num;
|
|
757
|
+
return (
|
|
758
|
+
<KeyButton
|
|
759
|
+
key={num}
|
|
760
|
+
isPressed={isPressed}
|
|
761
|
+
onClick={() => {
|
|
762
|
+
animateKeyPress(num);
|
|
763
|
+
handleKeyPress(displayChar);
|
|
764
|
+
if (shiftPressed) setShiftPressed(false);
|
|
765
|
+
}}
|
|
766
|
+
>
|
|
767
|
+
{displayChar}
|
|
768
|
+
</KeyButton>
|
|
769
|
+
);
|
|
770
|
+
})}
|
|
771
|
+
</div>
|
|
772
|
+
)}
|
|
773
|
+
|
|
774
|
+
{/* Symbol rows - shows when symbol mode is active */}
|
|
775
|
+
{symbolMode && (
|
|
776
|
+
<>
|
|
777
|
+
{/* Row 1: Special symbols - 10 keys balanced */}
|
|
778
|
+
<div className="flex gap-3 justify-center">
|
|
779
|
+
{["!", "@", "#", "$", "%", "^", "&", "*", "(", ")"].map((sym) => (
|
|
780
|
+
<SymbolButton key={sym} sym={sym} />
|
|
781
|
+
))}
|
|
782
|
+
</div>
|
|
783
|
+
{/* Row 2: Brackets and quotes - 10 keys balanced */}
|
|
784
|
+
<div className="flex gap-3 justify-center">
|
|
785
|
+
{["[", "]", "{", "}", "|", "\\", ";", ":", "'", '"'].map((sym) => (
|
|
786
|
+
<SymbolButton key={sym} sym={sym} />
|
|
787
|
+
))}
|
|
788
|
+
</div>
|
|
789
|
+
{/* Row 3: Punctuation and operators - 9 keys */}
|
|
790
|
+
<div className="flex gap-3 justify-center">
|
|
791
|
+
{[",", ".", "/", "?", "+", "-", "=", "_", "~"].map((sym) => (
|
|
792
|
+
<SymbolButton key={sym} sym={sym} />
|
|
793
|
+
))}
|
|
794
|
+
{showBackspace && (
|
|
795
|
+
<button
|
|
796
|
+
type="button"
|
|
797
|
+
disabled={disabled || actualInputValue.length === 0}
|
|
798
|
+
onClick={handleBackspace}
|
|
799
|
+
style={customKeyStyle}
|
|
800
|
+
className={cn(
|
|
801
|
+
BACKSPACE_BUTTON_CLASSES,
|
|
802
|
+
buttonClassName,
|
|
803
|
+
customKeyClassName
|
|
804
|
+
)}
|
|
805
|
+
>
|
|
806
|
+
<Delete className="mx-auto h-6 w-6" />
|
|
807
|
+
</button>
|
|
808
|
+
)}
|
|
809
|
+
</div>
|
|
810
|
+
</>
|
|
811
|
+
)}
|
|
812
|
+
|
|
813
|
+
{/* Letter rows - hidden when symbol mode is active */}
|
|
814
|
+
{!symbolMode && (
|
|
815
|
+
<>
|
|
816
|
+
{/* Row 1 - Letter row Q-P */}
|
|
817
|
+
<div className="flex gap-3 justify-center">
|
|
818
|
+
{keyboardLayout.row1.map((keyChar) => (
|
|
819
|
+
<LetterButton key={keyChar} keyChar={keyChar} />
|
|
820
|
+
))}
|
|
821
|
+
</div>
|
|
822
|
+
|
|
823
|
+
{/* Row 2 */}
|
|
824
|
+
<div className="flex gap-3 justify-center">
|
|
825
|
+
{keyboardLayout.row2.map((keyChar) => (
|
|
826
|
+
<LetterButton key={keyChar} keyChar={keyChar} />
|
|
827
|
+
))}
|
|
828
|
+
</div>
|
|
829
|
+
</>
|
|
830
|
+
)}
|
|
831
|
+
|
|
832
|
+
{/* Row 3 - Bottom letter row with controls */}
|
|
833
|
+
<div className="flex gap-3 justify-center">
|
|
834
|
+
{!symbolMode && (
|
|
835
|
+
<>
|
|
836
|
+
{showShift && (
|
|
837
|
+
<KeyButton
|
|
838
|
+
compact
|
|
839
|
+
isPressed={pressedKey === "CapsLock" && !capsLock}
|
|
840
|
+
onClick={toggleCapsLock}
|
|
841
|
+
className={capsLock ? ACTIVE_TOGGLE_CLASSES : ""}
|
|
842
|
+
>
|
|
843
|
+
<ArrowLeft className="h-6 w-6 rotate-90" />
|
|
844
|
+
</KeyButton>
|
|
845
|
+
)}
|
|
846
|
+
{keyboardLayout.row3.map((keyChar) => (
|
|
847
|
+
<LetterButton key={keyChar} keyChar={keyChar} />
|
|
848
|
+
))}
|
|
849
|
+
{showBackspace && (
|
|
850
|
+
<button
|
|
851
|
+
type="button"
|
|
852
|
+
disabled={disabled || actualInputValue.length === 0}
|
|
853
|
+
onClick={handleBackspace}
|
|
854
|
+
style={customKeyStyle}
|
|
855
|
+
className={cn(
|
|
856
|
+
BACKSPACE_BUTTON_CLASSES,
|
|
857
|
+
buttonClassName,
|
|
858
|
+
customKeyClassName
|
|
859
|
+
)}
|
|
860
|
+
>
|
|
861
|
+
<Delete className="mx-auto h-6 w-6" />
|
|
862
|
+
</button>
|
|
863
|
+
)}
|
|
864
|
+
</>
|
|
865
|
+
)}
|
|
866
|
+
</div>
|
|
867
|
+
|
|
868
|
+
{/* Bottom row */}
|
|
869
|
+
<div className="flex gap-3 justify-center">
|
|
870
|
+
<KeyButton
|
|
871
|
+
compact
|
|
872
|
+
isPressed={pressedKey === "#+=" && !symbolMode}
|
|
873
|
+
onClick={toggleSymbolMode}
|
|
874
|
+
className={symbolMode ? ACTIVE_TOGGLE_CLASSES : ""}
|
|
875
|
+
>
|
|
876
|
+
#+=
|
|
877
|
+
</KeyButton>
|
|
878
|
+
{showSpace && (
|
|
879
|
+
<Button
|
|
880
|
+
type="button"
|
|
881
|
+
disabled={disabled}
|
|
882
|
+
onClick={handleSpace}
|
|
883
|
+
style={customKeyStyle}
|
|
884
|
+
className={cn(
|
|
885
|
+
SPACE_BUTTON_CLASSES,
|
|
886
|
+
pressedKey === "Space" && PRESSED_KEY_CLASSES,
|
|
887
|
+
buttonClassName,
|
|
888
|
+
customKeyClassName
|
|
889
|
+
)}
|
|
890
|
+
>
|
|
891
|
+
Space
|
|
892
|
+
</Button>
|
|
893
|
+
)}
|
|
894
|
+
{showEnter && (
|
|
895
|
+
<Button
|
|
896
|
+
type="button"
|
|
897
|
+
disabled={disabled}
|
|
898
|
+
onClick={handleEnter}
|
|
899
|
+
style={customKeyStyle}
|
|
900
|
+
className={cn(
|
|
901
|
+
ENTER_BUTTON_CLASSES,
|
|
902
|
+
buttonClassName,
|
|
903
|
+
customKeyClassName
|
|
904
|
+
)}
|
|
905
|
+
>
|
|
906
|
+
<CornerDownLeft className="mx-auto h-6 w-6" />
|
|
907
|
+
</Button>
|
|
908
|
+
)}
|
|
909
|
+
</div>
|
|
910
|
+
</div>
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
Keyboard.displayName = "Keyboard";
|
|
915
|
+
|
|
916
|
+
export default Keyboard;
|