@cyberskill/design 1.0.0
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/DESIGN.md +267 -0
- package/README.md +316 -0
- package/SKILL.md +64 -0
- package/VERSION +1 -0
- package/_ds_bundle.js +5377 -0
- package/_ds_manifest.json +1 -0
- package/_esm/cs.mjs +137 -0
- package/assets/aurora-gold.jpg +0 -0
- package/assets/aurora-hoa.png +0 -0
- package/assets/aurora-kim.png +0 -0
- package/assets/aurora-moc.png +0 -0
- package/assets/aurora-thuy.png +0 -0
- package/assets/favicon.svg +1 -0
- package/assets/logo-mark.png +0 -0
- package/assets/logo-mark.svg +10 -0
- package/assets/lumi-poster.webp +0 -0
- package/assets/og-dashboard.png +0 -0
- package/base/a11y.css +57 -0
- package/base/ai.css +67 -0
- package/base/collections.css +53 -0
- package/base/components.css +212 -0
- package/base/controls.css +329 -0
- package/base/data.css +48 -0
- package/base/feedback.css +60 -0
- package/base/forms.css +32 -0
- package/base/glass.css +119 -0
- package/base/interaction.css +50 -0
- package/base/navigation.css +39 -0
- package/base/reset.css +17 -0
- package/base/responsive.css +128 -0
- package/base/shell.css +55 -0
- package/base/typography.css +14 -0
- package/components/_i18n/i18n.js +56 -0
- package/components/_i18n/strings.js +187 -0
- package/components/_utils/cx.js +4 -0
- package/components/ai/AIDisclosureBadge.d.ts +16 -0
- package/components/ai/AIDisclosureBadge.figma.tsx +12 -0
- package/components/ai/AIDisclosureBadge.jsx +39 -0
- package/components/ai/AIDisclosureBadge.prompt.md +9 -0
- package/components/ai/ChatMessage.d.ts +17 -0
- package/components/ai/ChatMessage.figma.tsx +12 -0
- package/components/ai/ChatMessage.jsx +22 -0
- package/components/ai/ChatMessage.prompt.md +8 -0
- package/components/ai/CitationList.d.ts +13 -0
- package/components/ai/CitationList.figma.tsx +12 -0
- package/components/ai/CitationList.jsx +22 -0
- package/components/ai/CitationList.prompt.md +5 -0
- package/components/ai/ConfidenceMeter.d.ts +17 -0
- package/components/ai/ConfidenceMeter.figma.tsx +12 -0
- package/components/ai/ConfidenceMeter.jsx +43 -0
- package/components/ai/ConfidenceMeter.prompt.md +6 -0
- package/components/ai/HumanReviewGate.d.ts +20 -0
- package/components/ai/HumanReviewGate.figma.tsx +12 -0
- package/components/ai/HumanReviewGate.jsx +37 -0
- package/components/ai/HumanReviewGate.prompt.md +13 -0
- package/components/ai/PromptInput.d.ts +21 -0
- package/components/ai/PromptInput.figma.tsx +12 -0
- package/components/ai/PromptInput.jsx +48 -0
- package/components/ai/PromptInput.prompt.md +5 -0
- package/components/ai/PromptSuggestions.d.ts +12 -0
- package/components/ai/PromptSuggestions.figma.tsx +12 -0
- package/components/ai/PromptSuggestions.jsx +20 -0
- package/components/ai/PromptSuggestions.prompt.md +5 -0
- package/components/ai/TypingIndicator.d.ts +9 -0
- package/components/ai/TypingIndicator.figma.tsx +12 -0
- package/components/ai/TypingIndicator.jsx +14 -0
- package/components/ai/TypingIndicator.prompt.md +5 -0
- package/components/ai/ai-conversation.card.html +49 -0
- package/components/ai/ai-lumi.card.html +39 -0
- package/components/ai/ai.card.html +43 -0
- package/components/brand/LumiAvatar.d.ts +14 -0
- package/components/brand/LumiAvatar.figma.tsx +12 -0
- package/components/brand/LumiAvatar.jsx +11 -0
- package/components/brand/LumiAvatar.prompt.md +5 -0
- package/components/brand/brand.card.html +37 -0
- package/components/button/Button.d.ts +24 -0
- package/components/button/Button.figma.tsx +31 -0
- package/components/button/Button.jsx +42 -0
- package/components/button/Button.prompt.md +12 -0
- package/components/button/ButtonGroup.d.ts +11 -0
- package/components/button/ButtonGroup.figma.tsx +12 -0
- package/components/button/ButtonGroup.jsx +7 -0
- package/components/button/ButtonGroup.prompt.md +8 -0
- package/components/button/FloatingActionButton.d.ts +15 -0
- package/components/button/FloatingActionButton.figma.tsx +12 -0
- package/components/button/FloatingActionButton.jsx +20 -0
- package/components/button/FloatingActionButton.prompt.md +6 -0
- package/components/button/buttons.card.html +52 -0
- package/components/data/Accordion.d.ts +14 -0
- package/components/data/Accordion.figma.tsx +12 -0
- package/components/data/Accordion.jsx +25 -0
- package/components/data/Accordion.prompt.md +5 -0
- package/components/data/Avatar.d.ts +18 -0
- package/components/data/Avatar.figma.tsx +12 -0
- package/components/data/Avatar.jsx +17 -0
- package/components/data/Avatar.prompt.md +6 -0
- package/components/data/Card.d.ts +23 -0
- package/components/data/Card.figma.tsx +12 -0
- package/components/data/Card.jsx +27 -0
- package/components/data/Card.prompt.md +9 -0
- package/components/data/Carousel.d.ts +13 -0
- package/components/data/Carousel.figma.tsx +12 -0
- package/components/data/Carousel.jsx +26 -0
- package/components/data/Carousel.prompt.md +5 -0
- package/components/data/Chart.d.ts +17 -0
- package/components/data/Chart.figma.tsx +12 -0
- package/components/data/Chart.jsx +52 -0
- package/components/data/Chart.prompt.md +5 -0
- package/components/data/CodeBlock.d.ts +12 -0
- package/components/data/CodeBlock.figma.tsx +12 -0
- package/components/data/CodeBlock.jsx +21 -0
- package/components/data/CodeBlock.prompt.md +5 -0
- package/components/data/Comment.d.ts +18 -0
- package/components/data/Comment.figma.tsx +12 -0
- package/components/data/Comment.jsx +24 -0
- package/components/data/Comment.prompt.md +7 -0
- package/components/data/DescriptionList.d.ts +10 -0
- package/components/data/DescriptionList.figma.tsx +12 -0
- package/components/data/DescriptionList.jsx +16 -0
- package/components/data/DescriptionList.prompt.md +5 -0
- package/components/data/Divider.d.ts +13 -0
- package/components/data/Divider.figma.tsx +12 -0
- package/components/data/Divider.jsx +11 -0
- package/components/data/Divider.prompt.md +6 -0
- package/components/data/Image.d.ts +18 -0
- package/components/data/Image.figma.tsx +12 -0
- package/components/data/Image.jsx +37 -0
- package/components/data/Image.prompt.md +5 -0
- package/components/data/Kbd.d.ts +8 -0
- package/components/data/Kbd.figma.tsx +12 -0
- package/components/data/Kbd.jsx +7 -0
- package/components/data/Kbd.prompt.md +5 -0
- package/components/data/List.d.ts +16 -0
- package/components/data/List.figma.tsx +12 -0
- package/components/data/List.jsx +24 -0
- package/components/data/List.prompt.md +7 -0
- package/components/data/Masonry.d.ts +13 -0
- package/components/data/Masonry.figma.tsx +12 -0
- package/components/data/Masonry.jsx +11 -0
- package/components/data/Masonry.prompt.md +5 -0
- package/components/data/QRCode.d.ts +12 -0
- package/components/data/QRCode.figma.tsx +12 -0
- package/components/data/QRCode.jsx +17 -0
- package/components/data/QRCode.prompt.md +5 -0
- package/components/data/Sortable.d.ts +10 -0
- package/components/data/Sortable.figma.tsx +12 -0
- package/components/data/Sortable.jsx +30 -0
- package/components/data/Sortable.prompt.md +5 -0
- package/components/data/Splitter.d.ts +16 -0
- package/components/data/Splitter.figma.tsx +12 -0
- package/components/data/Splitter.jsx +31 -0
- package/components/data/Splitter.prompt.md +5 -0
- package/components/data/Stat.d.ts +15 -0
- package/components/data/Stat.figma.tsx +12 -0
- package/components/data/Stat.jsx +19 -0
- package/components/data/Stat.prompt.md +5 -0
- package/components/data/Terminal.d.ts +13 -0
- package/components/data/Terminal.figma.tsx +12 -0
- package/components/data/Terminal.jsx +32 -0
- package/components/data/Terminal.prompt.md +5 -0
- package/components/data/Timeline.d.ts +17 -0
- package/components/data/Timeline.figma.tsx +12 -0
- package/components/data/Timeline.jsx +20 -0
- package/components/data/Timeline.prompt.md +8 -0
- package/components/data/Tooltip.d.ts +14 -0
- package/components/data/Tooltip.figma.tsx +12 -0
- package/components/data/Tooltip.jsx +12 -0
- package/components/data/Tooltip.prompt.md +5 -0
- package/components/data/Tree.d.ts +13 -0
- package/components/data/Tree.figma.tsx +12 -0
- package/components/data/Tree.jsx +23 -0
- package/components/data/Tree.prompt.md +5 -0
- package/components/data/Watermark.d.ts +15 -0
- package/components/data/Watermark.figma.tsx +12 -0
- package/components/data/Watermark.jsx +15 -0
- package/components/data/Watermark.prompt.md +5 -0
- package/components/data/collections.card.html +52 -0
- package/components/data/data.card.html +50 -0
- package/components/data/qr-encode.js +80 -0
- package/components/datatable/DataGrid.d.ts +42 -0
- package/components/datatable/DataGrid.figma.tsx +12 -0
- package/components/datatable/DataGrid.jsx +149 -0
- package/components/datatable/DataGrid.prompt.md +12 -0
- package/components/datatable/DataTable.d.ts +25 -0
- package/components/datatable/DataTable.figma.tsx +12 -0
- package/components/datatable/DataTable.jsx +42 -0
- package/components/datatable/DataTable.prompt.md +15 -0
- package/components/datatable/TreeTable.d.ts +14 -0
- package/components/datatable/TreeTable.figma.tsx +12 -0
- package/components/datatable/TreeTable.jsx +47 -0
- package/components/datatable/TreeTable.prompt.md +6 -0
- package/components/datatable/datatable.card.html +51 -0
- package/components/dialog/Dialog.d.ts +22 -0
- package/components/dialog/Dialog.figma.tsx +12 -0
- package/components/dialog/Dialog.jsx +99 -0
- package/components/dialog/Dialog.prompt.md +17 -0
- package/components/dialog/dialog.card.html +46 -0
- package/components/feedback/Alert.d.ts +16 -0
- package/components/feedback/Alert.figma.tsx +17 -0
- package/components/feedback/Alert.jsx +29 -0
- package/components/feedback/Alert.prompt.md +6 -0
- package/components/feedback/Badge.d.ts +15 -0
- package/components/feedback/Badge.figma.tsx +12 -0
- package/components/feedback/Badge.jsx +12 -0
- package/components/feedback/Badge.prompt.md +6 -0
- package/components/feedback/EmptyState.d.ts +13 -0
- package/components/feedback/EmptyState.figma.tsx +12 -0
- package/components/feedback/EmptyState.jsx +16 -0
- package/components/feedback/EmptyState.prompt.md +7 -0
- package/components/feedback/ProgressBar.d.ts +15 -0
- package/components/feedback/ProgressBar.figma.tsx +12 -0
- package/components/feedback/ProgressBar.jsx +13 -0
- package/components/feedback/ProgressBar.prompt.md +5 -0
- package/components/feedback/Result.d.ts +15 -0
- package/components/feedback/Result.figma.tsx +12 -0
- package/components/feedback/Result.jsx +24 -0
- package/components/feedback/Result.prompt.md +7 -0
- package/components/feedback/Skeleton.d.ts +18 -0
- package/components/feedback/Skeleton.figma.tsx +12 -0
- package/components/feedback/Skeleton.jsx +22 -0
- package/components/feedback/Skeleton.prompt.md +6 -0
- package/components/feedback/Spinner.d.ts +11 -0
- package/components/feedback/Spinner.figma.tsx +12 -0
- package/components/feedback/Spinner.jsx +10 -0
- package/components/feedback/Spinner.prompt.md +5 -0
- package/components/feedback/StatusIndicator.d.ts +11 -0
- package/components/feedback/StatusIndicator.figma.tsx +12 -0
- package/components/feedback/StatusIndicator.jsx +12 -0
- package/components/feedback/StatusIndicator.prompt.md +5 -0
- package/components/feedback/Tag.d.ts +14 -0
- package/components/feedback/Tag.figma.tsx +12 -0
- package/components/feedback/Tag.jsx +19 -0
- package/components/feedback/Tag.prompt.md +6 -0
- package/components/feedback/Toast.d.ts +19 -0
- package/components/feedback/Toast.figma.tsx +12 -0
- package/components/feedback/Toast.jsx +30 -0
- package/components/feedback/Toast.prompt.md +7 -0
- package/components/feedback/feedback-2.card.html +43 -0
- package/components/feedback/feedback.card.html +50 -0
- package/components/forms/Calendar.d.ts +10 -0
- package/components/forms/Calendar.figma.tsx +12 -0
- package/components/forms/Calendar.jsx +43 -0
- package/components/forms/Calendar.prompt.md +5 -0
- package/components/forms/Cascader.d.ts +17 -0
- package/components/forms/Cascader.figma.tsx +12 -0
- package/components/forms/Cascader.jsx +58 -0
- package/components/forms/Cascader.prompt.md +5 -0
- package/components/forms/Checkbox.d.ts +13 -0
- package/components/forms/Checkbox.figma.tsx +12 -0
- package/components/forms/Checkbox.jsx +16 -0
- package/components/forms/Checkbox.prompt.md +6 -0
- package/components/forms/ColorPicker.d.ts +12 -0
- package/components/forms/ColorPicker.figma.tsx +12 -0
- package/components/forms/ColorPicker.jsx +44 -0
- package/components/forms/ColorPicker.prompt.md +5 -0
- package/components/forms/Combobox.d.ts +17 -0
- package/components/forms/Combobox.figma.tsx +12 -0
- package/components/forms/Combobox.jsx +49 -0
- package/components/forms/Combobox.prompt.md +6 -0
- package/components/forms/DatePicker.d.ts +15 -0
- package/components/forms/DatePicker.figma.tsx +12 -0
- package/components/forms/DatePicker.jsx +35 -0
- package/components/forms/DatePicker.prompt.md +5 -0
- package/components/forms/Editor.d.ts +12 -0
- package/components/forms/Editor.figma.tsx +12 -0
- package/components/forms/Editor.jsx +26 -0
- package/components/forms/Editor.prompt.md +5 -0
- package/components/forms/FileUpload.d.ts +14 -0
- package/components/forms/FileUpload.figma.tsx +12 -0
- package/components/forms/FileUpload.jsx +29 -0
- package/components/forms/FileUpload.prompt.md +5 -0
- package/components/forms/Form.d.ts +87 -0
- package/components/forms/Form.figma.tsx +12 -0
- package/components/forms/Form.jsx +316 -0
- package/components/forms/Form.prompt.md +46 -0
- package/components/forms/InlineEdit.d.ts +13 -0
- package/components/forms/InlineEdit.figma.tsx +12 -0
- package/components/forms/InlineEdit.jsx +27 -0
- package/components/forms/InlineEdit.prompt.md +5 -0
- package/components/forms/InputGroup.d.ts +20 -0
- package/components/forms/InputGroup.figma.tsx +12 -0
- package/components/forms/InputGroup.jsx +25 -0
- package/components/forms/InputGroup.prompt.md +6 -0
- package/components/forms/InputOTP.d.ts +16 -0
- package/components/forms/InputOTP.figma.tsx +12 -0
- package/components/forms/InputOTP.jsx +47 -0
- package/components/forms/InputOTP.prompt.md +5 -0
- package/components/forms/Mentions.d.ts +13 -0
- package/components/forms/Mentions.figma.tsx +12 -0
- package/components/forms/Mentions.jsx +31 -0
- package/components/forms/Mentions.prompt.md +5 -0
- package/components/forms/NumberField.d.ts +14 -0
- package/components/forms/NumberField.figma.tsx +12 -0
- package/components/forms/NumberField.jsx +21 -0
- package/components/forms/NumberField.prompt.md +5 -0
- package/components/forms/RadioGroup.d.ts +24 -0
- package/components/forms/RadioGroup.figma.tsx +12 -0
- package/components/forms/RadioGroup.jsx +32 -0
- package/components/forms/RadioGroup.prompt.md +6 -0
- package/components/forms/Rating.d.ts +16 -0
- package/components/forms/Rating.figma.tsx +12 -0
- package/components/forms/Rating.jsx +22 -0
- package/components/forms/Rating.prompt.md +6 -0
- package/components/forms/SearchField.d.ts +11 -0
- package/components/forms/SearchField.figma.tsx +12 -0
- package/components/forms/SearchField.jsx +25 -0
- package/components/forms/SearchField.prompt.md +5 -0
- package/components/forms/SegmentedControl.d.ts +13 -0
- package/components/forms/SegmentedControl.figma.tsx +12 -0
- package/components/forms/SegmentedControl.jsx +31 -0
- package/components/forms/SegmentedControl.prompt.md +6 -0
- package/components/forms/Select.d.ts +19 -0
- package/components/forms/Select.figma.tsx +12 -0
- package/components/forms/Select.jsx +27 -0
- package/components/forms/Select.prompt.md +6 -0
- package/components/forms/Slider.d.ts +6 -0
- package/components/forms/Slider.figma.tsx +12 -0
- package/components/forms/Slider.jsx +8 -0
- package/components/forms/Slider.prompt.md +5 -0
- package/components/forms/Switch.d.ts +12 -0
- package/components/forms/Switch.figma.tsx +12 -0
- package/components/forms/Switch.jsx +14 -0
- package/components/forms/Switch.prompt.md +5 -0
- package/components/forms/TagInput.d.ts +16 -0
- package/components/forms/TagInput.figma.tsx +12 -0
- package/components/forms/TagInput.jsx +39 -0
- package/components/forms/TagInput.prompt.md +5 -0
- package/components/forms/Textarea.d.ts +14 -0
- package/components/forms/Textarea.figma.tsx +12 -0
- package/components/forms/Textarea.jsx +19 -0
- package/components/forms/Textarea.prompt.md +5 -0
- package/components/forms/TimePicker.d.ts +16 -0
- package/components/forms/TimePicker.figma.tsx +12 -0
- package/components/forms/TimePicker.jsx +22 -0
- package/components/forms/TimePicker.prompt.md +5 -0
- package/components/forms/Toggle.d.ts +16 -0
- package/components/forms/Toggle.figma.tsx +12 -0
- package/components/forms/Toggle.jsx +15 -0
- package/components/forms/Toggle.prompt.md +6 -0
- package/components/forms/Transfer.d.ts +14 -0
- package/components/forms/Transfer.figma.tsx +12 -0
- package/components/forms/Transfer.jsx +41 -0
- package/components/forms/Transfer.prompt.md +5 -0
- package/components/forms/TreeSelect.d.ts +15 -0
- package/components/forms/TreeSelect.figma.tsx +12 -0
- package/components/forms/TreeSelect.jsx +35 -0
- package/components/forms/TreeSelect.prompt.md +5 -0
- package/components/forms/forms-2.card.html +40 -0
- package/components/forms/forms.card.html +40 -0
- package/components/icon/Icon.d.ts +26 -0
- package/components/icon/Icon.figma.tsx +12 -0
- package/components/icon/Icon.jsx +74 -0
- package/components/icon/Icon.prompt.md +8 -0
- package/components/icon/icon.card.html +38 -0
- package/components/logo/Logo.d.ts +18 -0
- package/components/logo/Logo.figma.tsx +12 -0
- package/components/logo/Logo.jsx +25 -0
- package/components/logo/Logo.prompt.md +10 -0
- package/components/logo/logo-data.js +214 -0
- package/components/logo/logo.card.html +44 -0
- package/components/navigation/Anchor.d.ts +11 -0
- package/components/navigation/Anchor.figma.tsx +12 -0
- package/components/navigation/Anchor.jsx +25 -0
- package/components/navigation/Anchor.prompt.md +5 -0
- package/components/navigation/BackTop.d.ts +9 -0
- package/components/navigation/BackTop.figma.tsx +12 -0
- package/components/navigation/BackTop.jsx +23 -0
- package/components/navigation/BackTop.prompt.md +5 -0
- package/components/navigation/Breadcrumb.d.ts +14 -0
- package/components/navigation/Breadcrumb.figma.tsx +12 -0
- package/components/navigation/Breadcrumb.jsx +24 -0
- package/components/navigation/Breadcrumb.prompt.md +5 -0
- package/components/navigation/CommandPalette.d.ts +19 -0
- package/components/navigation/CommandPalette.figma.tsx +12 -0
- package/components/navigation/CommandPalette.jsx +48 -0
- package/components/navigation/CommandPalette.prompt.md +7 -0
- package/components/navigation/Dock.d.ts +6 -0
- package/components/navigation/Dock.figma.tsx +12 -0
- package/components/navigation/Dock.jsx +22 -0
- package/components/navigation/Dock.prompt.md +5 -0
- package/components/navigation/HotKeys.d.ts +13 -0
- package/components/navigation/HotKeys.figma.tsx +12 -0
- package/components/navigation/HotKeys.jsx +44 -0
- package/components/navigation/HotKeys.prompt.md +5 -0
- package/components/navigation/Link.d.ts +12 -0
- package/components/navigation/Link.figma.tsx +12 -0
- package/components/navigation/Link.jsx +13 -0
- package/components/navigation/Link.prompt.md +5 -0
- package/components/navigation/Menu.d.ts +23 -0
- package/components/navigation/Menu.figma.tsx +12 -0
- package/components/navigation/Menu.jsx +36 -0
- package/components/navigation/Menu.prompt.md +9 -0
- package/components/navigation/Menubar.d.ts +7 -0
- package/components/navigation/Menubar.figma.tsx +12 -0
- package/components/navigation/Menubar.jsx +48 -0
- package/components/navigation/Menubar.prompt.md +5 -0
- package/components/navigation/NavigationMenu.d.ts +7 -0
- package/components/navigation/NavigationMenu.figma.tsx +12 -0
- package/components/navigation/NavigationMenu.jsx +38 -0
- package/components/navigation/NavigationMenu.prompt.md +5 -0
- package/components/navigation/Pagination.d.ts +13 -0
- package/components/navigation/Pagination.figma.tsx +12 -0
- package/components/navigation/Pagination.jsx +32 -0
- package/components/navigation/Pagination.prompt.md +5 -0
- package/components/navigation/Sidebar.d.ts +20 -0
- package/components/navigation/Sidebar.figma.tsx +12 -0
- package/components/navigation/Sidebar.jsx +24 -0
- package/components/navigation/Sidebar.prompt.md +8 -0
- package/components/navigation/Steps.d.ts +13 -0
- package/components/navigation/Steps.figma.tsx +12 -0
- package/components/navigation/Steps.jsx +20 -0
- package/components/navigation/Steps.prompt.md +5 -0
- package/components/navigation/Tabs.d.ts +21 -0
- package/components/navigation/Tabs.figma.tsx +12 -0
- package/components/navigation/Tabs.jsx +41 -0
- package/components/navigation/Tabs.prompt.md +6 -0
- package/components/navigation/Toolbar.d.ts +16 -0
- package/components/navigation/Toolbar.figma.tsx +12 -0
- package/components/navigation/Toolbar.jsx +32 -0
- package/components/navigation/Toolbar.prompt.md +5 -0
- package/components/navigation/navigation.card.html +51 -0
- package/components/navigation/shell.card.html +52 -0
- package/components/overlays/ContextMenu.d.ts +10 -0
- package/components/overlays/ContextMenu.figma.tsx +12 -0
- package/components/overlays/ContextMenu.jsx +28 -0
- package/components/overlays/ContextMenu.prompt.md +7 -0
- package/components/overlays/Drawer.d.ts +18 -0
- package/components/overlays/Drawer.figma.tsx +12 -0
- package/components/overlays/Drawer.jsx +44 -0
- package/components/overlays/Drawer.prompt.md +8 -0
- package/components/overlays/HoverCard.d.ts +13 -0
- package/components/overlays/HoverCard.figma.tsx +12 -0
- package/components/overlays/HoverCard.jsx +17 -0
- package/components/overlays/HoverCard.prompt.md +5 -0
- package/components/overlays/Popconfirm.d.ts +18 -0
- package/components/overlays/Popconfirm.figma.tsx +12 -0
- package/components/overlays/Popconfirm.jsx +33 -0
- package/components/overlays/Popconfirm.prompt.md +6 -0
- package/components/overlays/Popover.d.ts +17 -0
- package/components/overlays/Popover.figma.tsx +12 -0
- package/components/overlays/Popover.jsx +24 -0
- package/components/overlays/Popover.prompt.md +7 -0
- package/components/overlays/Tour.d.ts +13 -0
- package/components/overlays/Tour.figma.tsx +12 -0
- package/components/overlays/Tour.jsx +46 -0
- package/components/overlays/Tour.prompt.md +5 -0
- package/components/overlays/overlays.card.html +50 -0
- package/components/textfield/TextField.d.ts +18 -0
- package/components/textfield/TextField.figma.tsx +14 -0
- package/components/textfield/TextField.jsx +44 -0
- package/components/textfield/TextField.prompt.md +11 -0
- package/components/textfield/textfield.card.html +34 -0
- package/docs/ci-cd.md +84 -0
- package/docs/consuming.md +109 -0
- package/docs/contrast-report.md +125 -0
- package/docs/conventions.md +114 -0
- package/docs/decisions.md +94 -0
- package/docs/deploy.md +110 -0
- package/docs/design-styles.md +25 -0
- package/docs/figma.md +119 -0
- package/docs/live-hub.md +58 -0
- package/docs/products.md +26 -0
- package/docs/quality-gates.md +94 -0
- package/docs/release-notes.md +31 -0
- package/docs/storybook.md +56 -0
- package/docs/sync.md +48 -0
- package/docs/template-schema-v2.md +36 -0
- package/docs/vi/ci-cd.md +84 -0
- package/docs/vi/consuming.md +109 -0
- package/docs/vi/contrast-report.md +125 -0
- package/docs/vi/conventions.md +114 -0
- package/docs/vi/decisions.md +94 -0
- package/docs/vi/deploy.md +110 -0
- package/docs/vi/design-styles.md +25 -0
- package/docs/vi/figma.md +119 -0
- package/docs/vi/live-hub.md +58 -0
- package/docs/vi/products.md +26 -0
- package/docs/vi/quality-gates.md +94 -0
- package/docs/vi/release-notes.md +31 -0
- package/docs/vi/storybook.md +56 -0
- package/docs/vi/sync.md +48 -0
- package/docs/vi/template-schema-v2.md +36 -0
- package/docs/viewer.html +230 -0
- package/fonts/bevietnampro-300-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-300-latin.woff2 +0 -0
- package/fonts/bevietnampro-300-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-400-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-400-latin.woff2 +0 -0
- package/fonts/bevietnampro-400-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-400i-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-400i-latin.woff2 +0 -0
- package/fonts/bevietnampro-400i-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-500-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-500-latin.woff2 +0 -0
- package/fonts/bevietnampro-500-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-600-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-600-latin.woff2 +0 -0
- package/fonts/bevietnampro-600-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-600i-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-600i-latin.woff2 +0 -0
- package/fonts/bevietnampro-600i-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-700-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-700-latin.woff2 +0 -0
- package/fonts/bevietnampro-700-vietnamese.woff2 +0 -0
- package/fonts/bevietnampro-800-latin-ext.woff2 +0 -0
- package/fonts/bevietnampro-800-latin.woff2 +0 -0
- package/fonts/bevietnampro-800-vietnamese.woff2 +0 -0
- package/fonts/jetbrainsmono-400-cyrillic-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-400-cyrillic.woff2 +0 -0
- package/fonts/jetbrainsmono-400-greek.woff2 +0 -0
- package/fonts/jetbrainsmono-400-latin-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-400-latin.woff2 +0 -0
- package/fonts/jetbrainsmono-400-vietnamese.woff2 +0 -0
- package/fonts/jetbrainsmono-500-cyrillic-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-500-cyrillic.woff2 +0 -0
- package/fonts/jetbrainsmono-500-greek.woff2 +0 -0
- package/fonts/jetbrainsmono-500-latin-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-500-latin.woff2 +0 -0
- package/fonts/jetbrainsmono-500-vietnamese.woff2 +0 -0
- package/fonts/jetbrainsmono-700-cyrillic-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-700-cyrillic.woff2 +0 -0
- package/fonts/jetbrainsmono-700-greek.woff2 +0 -0
- package/fonts/jetbrainsmono-700-latin-ext.woff2 +0 -0
- package/fonts/jetbrainsmono-700-latin.woff2 +0 -0
- package/fonts/jetbrainsmono-700-vietnamese.woff2 +0 -0
- package/guidelines/atomic-view.html +497 -0
- package/guidelines/brand-iconography.html +51 -0
- package/guidelines/brand-imagery.html +23 -0
- package/guidelines/brand-interaction.html +24 -0
- package/guidelines/brand-voice.html +24 -0
- package/guidelines/colors-anchors.html +20 -0
- package/guidelines/colors-semantic.html +19 -0
- package/guidelines/colors-surfaces.html +19 -0
- package/guidelines/colors-text.html +20 -0
- package/guidelines/documents.html +43 -0
- package/guidelines/elements-components.html +27 -0
- package/guidelines/elements-concept.html +48 -0
- package/guidelines/elements-variants.html +49 -0
- package/guidelines/motion-interaction.html +29 -0
- package/guidelines/motion.html +53 -0
- package/guidelines/nav-model.cjs +113 -0
- package/guidelines/responsive-bilingual.html +75 -0
- package/guidelines/rtl-preview.html +115 -0
- package/guidelines/spacing-breakpoints.html +20 -0
- package/guidelines/spacing-radius.html +19 -0
- package/guidelines/spacing-scale.html +21 -0
- package/guidelines/surfaces-aurora.html +20 -0
- package/guidelines/surfaces-depth.html +27 -0
- package/guidelines/surfaces-glass.html +21 -0
- package/guidelines/surfaces-shadow.html +20 -0
- package/guidelines/type-families.html +25 -0
- package/guidelines/type-lineheight.html +16 -0
- package/guidelines/type-scale.html +21 -0
- package/guidelines/type-weights.html +20 -0
- package/llms.txt +70 -0
- package/package.json +88 -0
- package/styles.css +39 -0
- package/templates/_vendor/deck-stage.js +2584 -0
- package/templates/ai-cluster-demo.html +46 -0
- package/templates/app-shell/.thumbnail +0 -0
- package/templates/app-shell/AppShell.dc.html +80 -0
- package/templates/app-shell/content-schema.json +114 -0
- package/templates/app-shell/ds-base.js +23 -0
- package/templates/app-shell/support.js +1841 -0
- package/templates/article/.thumbnail +0 -0
- package/templates/article/Article.dc.html +67 -0
- package/templates/article/content-schema.json +80 -0
- package/templates/article/ds-base.js +23 -0
- package/templates/article/support.js +1841 -0
- package/templates/auth/.thumbnail +0 -0
- package/templates/auth/Auth.dc.html +72 -0
- package/templates/auth/content-schema.json +74 -0
- package/templates/auth/ds-base.js +23 -0
- package/templates/auth/support.js +1841 -0
- package/templates/bod-deck/.thumbnail +0 -0
- package/templates/bod-deck/BodDeck.dc.html +106 -0
- package/templates/bod-deck/content-schema.json +171 -0
- package/templates/bod-deck/ds-base.js +23 -0
- package/templates/bod-deck/support.js +1841 -0
- package/templates/bod-investor-update/.thumbnail +0 -0
- package/templates/bod-investor-update/BodInvestorUpdate.dc.html +81 -0
- package/templates/bod-investor-update/content-schema.json +105 -0
- package/templates/bod-investor-update/ds-base.js +23 -0
- package/templates/bod-investor-update/support.js +1841 -0
- package/templates/bod-memo/.thumbnail +0 -0
- package/templates/bod-memo/BodMemo.dc.html +87 -0
- package/templates/bod-memo/ds-base.js +23 -0
- package/templates/bod-memo/support.js +1841 -0
- package/templates/bod-minutes/.thumbnail +0 -0
- package/templates/bod-minutes/BodMinutes.dc.html +84 -0
- package/templates/bod-minutes/ds-base.js +23 -0
- package/templates/bod-minutes/support.js +1841 -0
- package/templates/bod-report/.thumbnail +0 -0
- package/templates/bod-report/BodReport.dc.html +106 -0
- package/templates/bod-report/content-schema.json +29 -0
- package/templates/bod-report/ds-base.js +23 -0
- package/templates/bod-report/support.js +1841 -0
- package/templates/bod-resolution/.thumbnail +0 -0
- package/templates/bod-resolution/BodResolution.dc.html +87 -0
- package/templates/bod-resolution/content-schema.json +123 -0
- package/templates/bod-resolution/ds-base.js +23 -0
- package/templates/bod-resolution/support.js +1841 -0
- package/templates/culture-event-invite/.thumbnail +0 -0
- package/templates/culture-event-invite/CultureEventInvite.dc.html +73 -0
- package/templates/culture-event-invite/ds-base.js +23 -0
- package/templates/culture-event-invite/support.js +1841 -0
- package/templates/dashboard/.thumbnail +0 -0
- package/templates/dashboard/Dashboard.dc.html +120 -0
- package/templates/dashboard/content-schema.json +97 -0
- package/templates/dashboard/ds-base.js +23 -0
- package/templates/dashboard/support.js +1841 -0
- package/templates/delivery-change-note/.thumbnail +0 -0
- package/templates/delivery-change-note/DeliveryChangeNote.dc.html +85 -0
- package/templates/delivery-change-note/content-schema.json +158 -0
- package/templates/delivery-change-note/ds-base.js +23 -0
- package/templates/delivery-change-note/support.js +1841 -0
- package/templates/delivery-kickoff/.thumbnail +0 -0
- package/templates/delivery-kickoff/DeliveryKickoff.dc.html +112 -0
- package/templates/delivery-kickoff/content-schema.json +223 -0
- package/templates/delivery-kickoff/ds-base.js +23 -0
- package/templates/delivery-kickoff/support.js +1841 -0
- package/templates/delivery-qbr-deck/.thumbnail +0 -0
- package/templates/delivery-qbr-deck/DeliveryQbrDeck.dc.html +118 -0
- package/templates/delivery-qbr-deck/content-schema.json +177 -0
- package/templates/delivery-qbr-deck/ds-base.js +23 -0
- package/templates/delivery-qbr-deck/support.js +1841 -0
- package/templates/delivery-runbook/.thumbnail +0 -0
- package/templates/delivery-runbook/DeliveryRunbook.dc.html +91 -0
- package/templates/delivery-runbook/content-schema.json +211 -0
- package/templates/delivery-runbook/ds-base.js +23 -0
- package/templates/delivery-runbook/support.js +1841 -0
- package/templates/delivery-status-email/.thumbnail +0 -0
- package/templates/delivery-status-email/DeliveryStatusEmail.dc.html +78 -0
- package/templates/delivery-status-email/ds-base.js +23 -0
- package/templates/delivery-status-email/support.js +1841 -0
- package/templates/doc-style-guide/.thumbnail +0 -0
- package/templates/doc-style-guide/DocStyleGuide.dc.html +148 -0
- package/templates/doc-style-guide/ds-base.js +23 -0
- package/templates/doc-style-guide/support.js +1841 -0
- package/templates/doc-suite-index/.thumbnail +0 -0
- package/templates/doc-suite-index/DocSuiteIndex.dc.html +201 -0
- package/templates/doc-suite-index/content-schema.json +12 -0
- package/templates/doc-suite-index/ds-base.js +23 -0
- package/templates/doc-suite-index/support.js +1841 -0
- package/templates/doc-templates/.thumbnail +0 -0
- package/templates/doc-templates/DocTemplates.dc.html +118 -0
- package/templates/doc-templates/ds-base.js +23 -0
- package/templates/doc-templates/support.js +1841 -0
- package/templates/email/.thumbnail +0 -0
- package/templates/email/Email-VN-standalone.html +59 -0
- package/templates/email/Email.dc.html +67 -0
- package/templates/email/ds-base.js +23 -0
- package/templates/email/support.js +1841 -0
- package/templates/email-safe/README.md +28 -0
- package/templates/email-safe/email-announcement.html +88 -0
- package/templates/email-safe/email-dunning.html +59 -0
- package/templates/email-safe/email-investor.html +88 -0
- package/templates/email-safe/email-launch.html +88 -0
- package/templates/email-safe/email-newsletter.html +62 -0
- package/templates/email-safe/email-status.html +88 -0
- package/templates/email-safe/email-transactional.html +88 -0
- package/templates/finance-dunning-email/.thumbnail +0 -0
- package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +58 -0
- package/templates/finance-dunning-email/ds-base.js +23 -0
- package/templates/finance-dunning-email/support.js +1841 -0
- package/templates/finance-expense-report/.thumbnail +0 -0
- package/templates/finance-expense-report/FinanceExpenseReport.dc.html +82 -0
- package/templates/finance-expense-report/ds-base.js +23 -0
- package/templates/finance-expense-report/support.js +1841 -0
- package/templates/finance-invoice/.thumbnail +0 -0
- package/templates/finance-invoice/FinanceInvoice.dc.html +92 -0
- package/templates/finance-invoice/ds-base.js +23 -0
- package/templates/finance-invoice/support.js +1841 -0
- package/templates/finance-quote/.thumbnail +0 -0
- package/templates/finance-quote/FinanceQuote.dc.html +86 -0
- package/templates/finance-quote/ds-base.js +23 -0
- package/templates/finance-quote/support.js +1841 -0
- package/templates/hr-announcement/.thumbnail +0 -0
- package/templates/hr-announcement/HrAnnouncement.dc.html +64 -0
- package/templates/hr-announcement/ds-base.js +23 -0
- package/templates/hr-announcement/support.js +1841 -0
- package/templates/hr-interview-kit/.thumbnail +0 -0
- package/templates/hr-interview-kit/HrInterviewKit.dc.html +102 -0
- package/templates/hr-interview-kit/ds-base.js +23 -0
- package/templates/hr-interview-kit/support.js +1841 -0
- package/templates/hr-offboarding/.thumbnail +0 -0
- package/templates/hr-offboarding/HrOffboarding.dc.html +86 -0
- package/templates/hr-offboarding/ds-base.js +23 -0
- package/templates/hr-offboarding/support.js +1841 -0
- package/templates/hr-performance-review/.thumbnail +0 -0
- package/templates/hr-performance-review/HrPerformanceReview.dc.html +95 -0
- package/templates/hr-performance-review/ds-base.js +23 -0
- package/templates/hr-performance-review/support.js +1841 -0
- package/templates/hr-pip/.thumbnail +0 -0
- package/templates/hr-pip/HrPip.dc.html +73 -0
- package/templates/hr-pip/ds-base.js +23 -0
- package/templates/hr-pip/support.js +1841 -0
- package/templates/image-slots-demo.html +57 -0
- package/templates/kitchen-sink.html +127 -0
- package/templates/legal-msa/.thumbnail +0 -0
- package/templates/legal-msa/LegalMsa.dc.html +85 -0
- package/templates/legal-msa/ds-base.js +23 -0
- package/templates/legal-msa/support.js +1841 -0
- package/templates/legal-sow/.thumbnail +0 -0
- package/templates/legal-sow/LegalSow.dc.html +125 -0
- package/templates/legal-sow/ds-base.js +23 -0
- package/templates/legal-sow/support.js +1841 -0
- package/templates/marketing-campaign-brief/.thumbnail +0 -0
- package/templates/marketing-campaign-brief/MarketingCampaignBrief.dc.html +86 -0
- package/templates/marketing-campaign-brief/content-schema.json +139 -0
- package/templates/marketing-campaign-brief/ds-base.js +23 -0
- package/templates/marketing-campaign-brief/support.js +1841 -0
- package/templates/marketing-case-study/.thumbnail +0 -0
- package/templates/marketing-case-study/MarketingCaseStudy.dc.html +82 -0
- package/templates/marketing-case-study/content-schema.json +103 -0
- package/templates/marketing-case-study/ds-base.js +23 -0
- package/templates/marketing-case-study/support.js +1841 -0
- package/templates/marketing-launch/.thumbnail +0 -0
- package/templates/marketing-launch/MarketingLaunch.dc.html +84 -0
- package/templates/marketing-launch/ds-base.js +23 -0
- package/templates/marketing-launch/support.js +1841 -0
- package/templates/marketing-newsletter/.thumbnail +0 -0
- package/templates/marketing-newsletter/MarketingNewsletter.dc.html +109 -0
- package/templates/marketing-newsletter/ds-base.js +23 -0
- package/templates/marketing-newsletter/support.js +1841 -0
- package/templates/marketing-page/.thumbnail +0 -0
- package/templates/marketing-page/MarketingPage.dc.html +132 -0
- package/templates/marketing-page/content-schema.json +33 -0
- package/templates/marketing-page/ds-base.js +23 -0
- package/templates/marketing-page/support.js +1841 -0
- package/templates/marketing-press-release/.thumbnail +0 -0
- package/templates/marketing-press-release/MarketingPressRelease.dc.html +84 -0
- package/templates/marketing-press-release/content-schema.json +116 -0
- package/templates/marketing-press-release/ds-base.js +23 -0
- package/templates/marketing-press-release/support.js +1841 -0
- package/templates/marketing-social-kit/.thumbnail +0 -0
- package/templates/marketing-social-kit/MarketingSocialKit.dc.html +77 -0
- package/templates/marketing-social-kit/content-schema.json +54 -0
- package/templates/marketing-social-kit/ds-base.js +23 -0
- package/templates/marketing-social-kit/support.js +1841 -0
- package/templates/playground.html +79 -0
- package/templates/sales-one-pager/.thumbnail +0 -0
- package/templates/sales-one-pager/SalesOnePager.dc.html +103 -0
- package/templates/sales-one-pager/content-schema.json +73 -0
- package/templates/sales-one-pager/ds-base.js +23 -0
- package/templates/sales-one-pager/support.js +1841 -0
- package/templates/sales-proposal-deck/.thumbnail +0 -0
- package/templates/sales-proposal-deck/SalesProposalDeck.dc.html +159 -0
- package/templates/sales-proposal-deck/content-schema.json +273 -0
- package/templates/sales-proposal-deck/ds-base.js +23 -0
- package/templates/sales-proposal-deck/support.js +1841 -0
- package/templates/schema/content-schema.schema.json +31 -0
- package/templates/settings/.thumbnail +0 -0
- package/templates/settings/Settings.dc.html +86 -0
- package/templates/settings/content-schema.json +131 -0
- package/templates/settings/ds-base.js +23 -0
- package/templates/settings/support.js +1841 -0
- package/templates/slide-deck/.thumbnail +0 -0
- package/templates/slide-deck/SlideDeck.dc.html +86 -0
- package/templates/slide-deck/content-schema.json +23 -0
- package/templates/slide-deck/ds-base.js +23 -0
- package/templates/slide-deck/support.js +1841 -0
- package/templates/team-meeting-agenda/.thumbnail +0 -0
- package/templates/team-meeting-agenda/TeamMeetingAgenda.dc.html +93 -0
- package/templates/team-meeting-agenda/ds-base.js +23 -0
- package/templates/team-meeting-agenda/support.js +1841 -0
- package/templates/tech-incident-report/.thumbnail +0 -0
- package/templates/tech-incident-report/TechIncidentReport.dc.html +111 -0
- package/templates/tech-incident-report/content-schema.json +25 -0
- package/templates/tech-incident-report/ds-base.js +23 -0
- package/templates/tech-incident-report/support.js +1841 -0
- package/templates/tech-release-notes/.thumbnail +0 -0
- package/templates/tech-release-notes/TechReleaseNotes.dc.html +79 -0
- package/templates/tech-release-notes/ds-base.js +23 -0
- package/templates/tech-release-notes/support.js +1841 -0
- package/templates/tech-retro/.thumbnail +0 -0
- package/templates/tech-retro/TechRetro.dc.html +84 -0
- package/templates/tech-retro/ds-base.js +23 -0
- package/templates/tech-retro/support.js +1841 -0
- package/templates/tech-rfc/.thumbnail +0 -0
- package/templates/tech-rfc/TechRfc.dc.html +87 -0
- package/templates/tech-rfc/content-schema.json +115 -0
- package/templates/tech-rfc/ds-base.js +23 -0
- package/templates/tech-rfc/support.js +1841 -0
- package/templates/vn-appointment-transfer/.thumbnail +0 -0
- package/templates/vn-appointment-transfer/VnAppointmentTransfer.dc.html +101 -0
- package/templates/vn-appointment-transfer/ds-base.js +23 -0
- package/templates/vn-appointment-transfer/support.js +1841 -0
- package/templates/vn-certificate-of-employment/.thumbnail +0 -0
- package/templates/vn-certificate-of-employment/VnCertificateOfEmployment.dc.html +84 -0
- package/templates/vn-certificate-of-employment/ds-base.js +23 -0
- package/templates/vn-certificate-of-employment/support.js +1841 -0
- package/templates/vn-code-of-conduct/.thumbnail +0 -0
- package/templates/vn-code-of-conduct/VnCodeOfConduct.dc.html +105 -0
- package/templates/vn-code-of-conduct/ds-base.js +23 -0
- package/templates/vn-code-of-conduct/support.js +1841 -0
- package/templates/vn-compensation-regulation/.thumbnail +0 -0
- package/templates/vn-compensation-regulation/VnCompensationRegulation.dc.html +122 -0
- package/templates/vn-compensation-regulation/ds-base.js +23 -0
- package/templates/vn-compensation-regulation/support.js +1841 -0
- package/templates/vn-contract-amendment/.thumbnail +0 -0
- package/templates/vn-contract-amendment/VnContractAmendment.dc.html +107 -0
- package/templates/vn-contract-amendment/ds-base.js +23 -0
- package/templates/vn-contract-amendment/support.js +1841 -0
- package/templates/vn-contractor-agreement/.thumbnail +0 -0
- package/templates/vn-contractor-agreement/VnContractorAgreement.dc.html +120 -0
- package/templates/vn-contractor-agreement/ds-base.js +23 -0
- package/templates/vn-contractor-agreement/support.js +1841 -0
- package/templates/vn-data-protection-policy/.thumbnail +0 -0
- package/templates/vn-data-protection-policy/VnDataProtectionPolicy.dc.html +116 -0
- package/templates/vn-data-protection-policy/ds-base.js +23 -0
- package/templates/vn-data-protection-policy/support.js +1841 -0
- package/templates/vn-disciplinary-case-file/.thumbnail +0 -0
- package/templates/vn-disciplinary-case-file/VnDisciplinaryCaseFile.dc.html +172 -0
- package/templates/vn-disciplinary-case-file/ds-base.js +23 -0
- package/templates/vn-disciplinary-case-file/support.js +1841 -0
- package/templates/vn-disciplinary-schedule/.thumbnail +0 -0
- package/templates/vn-disciplinary-schedule/VnDisciplinarySchedule.dc.html +91 -0
- package/templates/vn-disciplinary-schedule/ds-base.js +23 -0
- package/templates/vn-disciplinary-schedule/support.js +1841 -0
- package/templates/vn-employee-request/.thumbnail +0 -0
- package/templates/vn-employee-request/VnEmployeeRequest.dc.html +137 -0
- package/templates/vn-employee-request/ds-base.js +23 -0
- package/templates/vn-employee-request/support.js +1841 -0
- package/templates/vn-exit-handover/.thumbnail +0 -0
- package/templates/vn-exit-handover/VnExitHandover.dc.html +228 -0
- package/templates/vn-exit-handover/ds-base.js +23 -0
- package/templates/vn-exit-handover/support.js +1841 -0
- package/templates/vn-foreign-employee-pack/.thumbnail +0 -0
- package/templates/vn-foreign-employee-pack/VnForeignEmployeePack.dc.html +129 -0
- package/templates/vn-foreign-employee-pack/content-schema.json +22 -0
- package/templates/vn-foreign-employee-pack/ds-base.js +23 -0
- package/templates/vn-foreign-employee-pack/support.js +1841 -0
- package/templates/vn-grassroots-democracy/.thumbnail +0 -0
- package/templates/vn-grassroots-democracy/VnGrassrootsDemocracy.dc.html +117 -0
- package/templates/vn-grassroots-democracy/ds-base.js +23 -0
- package/templates/vn-grassroots-democracy/support.js +1841 -0
- package/templates/vn-infosec-policy/.thumbnail +0 -0
- package/templates/vn-infosec-policy/VnInfosecPolicy.dc.html +116 -0
- package/templates/vn-infosec-policy/ds-base.js +23 -0
- package/templates/vn-infosec-policy/support.js +1841 -0
- package/templates/vn-internal-labor-regulations/.thumbnail +0 -0
- package/templates/vn-internal-labor-regulations/VnInternalLaborRegulations.dc.html +155 -0
- package/templates/vn-internal-labor-regulations/ds-base.js +23 -0
- package/templates/vn-internal-labor-regulations/support.js +1841 -0
- package/templates/vn-internship-agreement/.thumbnail +0 -0
- package/templates/vn-internship-agreement/VnInternshipAgreement.dc.html +112 -0
- package/templates/vn-internship-agreement/ds-base.js +23 -0
- package/templates/vn-internship-agreement/support.js +1841 -0
- package/templates/vn-job-description/.thumbnail +0 -0
- package/templates/vn-job-description/VnJobDescription.dc.html +85 -0
- package/templates/vn-job-description/ds-base.js +23 -0
- package/templates/vn-job-description/support.js +1841 -0
- package/templates/vn-labor-contract/.thumbnail +0 -0
- package/templates/vn-labor-contract/VnLaborContract.dc.html +180 -0
- package/templates/vn-labor-contract/ds-base.js +23 -0
- package/templates/vn-labor-contract/support.js +1841 -0
- package/templates/vn-labour-management-book/.thumbnail +0 -0
- package/templates/vn-labour-management-book/VnLabourManagementBook.dc.html +115 -0
- package/templates/vn-labour-management-book/ds-base.js +23 -0
- package/templates/vn-labour-management-book/support.js +1841 -0
- package/templates/vn-mutual-nda/.thumbnail +0 -0
- package/templates/vn-mutual-nda/VnMutualNda.dc.html +114 -0
- package/templates/vn-mutual-nda/ds-base.js +23 -0
- package/templates/vn-mutual-nda/support.js +1841 -0
- package/templates/vn-ndnca-ip/.thumbnail +0 -0
- package/templates/vn-ndnca-ip/VnNdncaIp.dc.html +157 -0
- package/templates/vn-ndnca-ip/ds-base.js +23 -0
- package/templates/vn-ndnca-ip/support.js +1841 -0
- package/templates/vn-offer-letter/.thumbnail +0 -0
- package/templates/vn-offer-letter/VnOfferLetter.dc.html +84 -0
- package/templates/vn-offer-letter/ds-base.js +23 -0
- package/templates/vn-offer-letter/support.js +1841 -0
- package/templates/vn-onboarding-checklist/.thumbnail +0 -0
- package/templates/vn-onboarding-checklist/VnOnboardingChecklist.dc.html +98 -0
- package/templates/vn-onboarding-checklist/content-schema.json +12 -0
- package/templates/vn-onboarding-checklist/ds-base.js +23 -0
- package/templates/vn-onboarding-checklist/support.js +1841 -0
- package/templates/vn-pdpl-consent/.thumbnail +0 -0
- package/templates/vn-pdpl-consent/VnPdplConsent.dc.html +111 -0
- package/templates/vn-pdpl-consent/ds-base.js +23 -0
- package/templates/vn-pdpl-consent/support.js +1841 -0
- package/templates/vn-performance-evaluation-regulation/.thumbnail +0 -0
- package/templates/vn-performance-evaluation-regulation/VnPerformanceEvaluationRegulation.dc.html +135 -0
- package/templates/vn-performance-evaluation-regulation/ds-base.js +23 -0
- package/templates/vn-performance-evaluation-regulation/support.js +1841 -0
- package/templates/vn-performance-review-form/.thumbnail +0 -0
- package/templates/vn-performance-review-form/VnPerformanceReviewForm.dc.html +129 -0
- package/templates/vn-performance-review-form/ds-base.js +23 -0
- package/templates/vn-performance-review-form/support.js +1841 -0
- package/templates/vn-phantom-stock/.thumbnail +0 -0
- package/templates/vn-phantom-stock/VnPhantomStock.dc.html +184 -0
- package/templates/vn-phantom-stock/content-schema.json +17 -0
- package/templates/vn-phantom-stock/ds-base.js +23 -0
- package/templates/vn-phantom-stock/support.js +1841 -0
- package/templates/vn-probation-contract/.thumbnail +0 -0
- package/templates/vn-probation-contract/VnProbationContract.dc.html +126 -0
- package/templates/vn-probation-contract/ds-base.js +23 -0
- package/templates/vn-probation-contract/support.js +1841 -0
- package/templates/vn-receipt-acknowledgement/.thumbnail +0 -0
- package/templates/vn-receipt-acknowledgement/VnReceiptAcknowledgement.dc.html +106 -0
- package/templates/vn-receipt-acknowledgement/ds-base.js +23 -0
- package/templates/vn-receipt-acknowledgement/support.js +1841 -0
- package/templates/vn-remote-work-policy/.thumbnail +0 -0
- package/templates/vn-remote-work-policy/VnRemoteWorkPolicy.dc.html +103 -0
- package/templates/vn-remote-work-policy/ds-base.js +23 -0
- package/templates/vn-remote-work-policy/support.js +1841 -0
- package/templates/vn-resignation-letter/.thumbnail +0 -0
- package/templates/vn-resignation-letter/VnResignationLetter.dc.html +71 -0
- package/templates/vn-resignation-letter/ds-base.js +23 -0
- package/templates/vn-resignation-letter/support.js +1841 -0
- package/templates/vn-salary-scale/.thumbnail +0 -0
- package/templates/vn-salary-scale/VnSalaryScale.dc.html +110 -0
- package/templates/vn-salary-scale/ds-base.js +23 -0
- package/templates/vn-salary-scale/support.js +1841 -0
- package/templates/vn-sow-appendix/.thumbnail +0 -0
- package/templates/vn-sow-appendix/VnSowAppendix.dc.html +70 -0
- package/templates/vn-sow-appendix/ds-base.js +23 -0
- package/templates/vn-sow-appendix/support.js +1841 -0
- package/templates/vn-termination-decision/.thumbnail +0 -0
- package/templates/vn-termination-decision/VnTerminationDecision.dc.html +80 -0
- package/templates/vn-termination-decision/ds-base.js +23 -0
- package/templates/vn-termination-decision/support.js +1841 -0
- package/templates/vn-total-rewards-appendix/.thumbnail +0 -0
- package/templates/vn-total-rewards-appendix/VnTotalRewardsAppendix.dc.html +138 -0
- package/templates/vn-total-rewards-appendix/ds-base.js +23 -0
- package/templates/vn-total-rewards-appendix/support.js +1841 -0
- package/templates/vn-training-commitment/.thumbnail +0 -0
- package/templates/vn-training-commitment/VnTrainingCommitment.dc.html +105 -0
- package/templates/vn-training-commitment/ds-base.js +23 -0
- package/templates/vn-training-commitment/support.js +1841 -0
- package/templates/vn-travel-expense-policy/.thumbnail +0 -0
- package/templates/vn-travel-expense-policy/VnTravelExpensePolicy.dc.html +113 -0
- package/templates/vn-travel-expense-policy/ds-base.js +23 -0
- package/templates/vn-travel-expense-policy/support.js +1841 -0
- package/tokens/colors.css +77 -0
- package/tokens/component-tokens.css +46 -0
- package/tokens/elements.css +300 -0
- package/tokens/elevation.css +46 -0
- package/tokens/fonts.css +51 -0
- package/tokens/motion.css +25 -0
- package/tokens/native/CSTokens.kt +255 -0
- package/tokens/native/CSTokens.swift +257 -0
- package/tokens/native/cs_tokens.dart +253 -0
- package/tokens/provenance.json +52 -0
- package/tokens/spacing.css +34 -0
- package/tokens/tokens.dtcg.json +1222 -0
- package/tokens/tokens.js +436 -0
- package/tokens/tokens.json +434 -0
- package/tokens/typography.css +67 -0
- package/tokens/viewer.html +261 -0
- package/ui_kits/deck/README.md +21 -0
- package/ui_kits/deck/index.html +120 -0
- package/ui_kits/status-hub/README.md +40 -0
- package/ui_kits/status-hub/StatusHub.jsx +270 -0
- package/ui_kits/status-hub/data.js +57 -0
- package/ui_kits/status-hub/identity-lab.html +134 -0
- package/ui_kits/status-hub/index.html +24 -0
- package/ui_kits/status-hub/login.html +65 -0
- package/ui_kits/status-hub/project.html +137 -0
- package/ui_kits/status-hub/settings.html +88 -0
- package/ui_kits/status-hub/status.css +199 -0
- package/ui_kits/website/README.md +36 -0
- package/ui_kits/website/Website.jsx +167 -0
- package/ui_kits/website/careers.html +109 -0
- package/ui_kits/website/chat.html +133 -0
- package/ui_kits/website/copy.js +76 -0
- package/ui_kits/website/index.html +24 -0
- package/ui_kits/website/site.css +121 -0
- package/ui_kits/website/work.html +119 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
|
+
import { cx } from "../_utils/cx.js";
|
|
4
|
+
|
|
5
|
+
/** CyberSkill FileUpload — click-or-drag dropzone. Calls onFiles(File[]) on select/drop. */
|
|
6
|
+
export function FileUpload({ title, hint, accept, multiple = false, onFiles, icon, lang, className }) {
|
|
7
|
+
const [drag, setDrag] = React.useState(false);
|
|
8
|
+
const pick = (files) => { if (files && files.length && onFiles) onFiles(Array.from(files)); };
|
|
9
|
+
const [ref, L] = useLang(lang);
|
|
10
|
+
const t = makeT("FileUpload", L);
|
|
11
|
+
const tt = title != null ? title : t("title");
|
|
12
|
+
const hh = hint != null ? hint : t("hint");
|
|
13
|
+
return (
|
|
14
|
+
<label
|
|
15
|
+
ref={ref}
|
|
16
|
+
className={cx("cs-dropzone", drag && "is-dragging", className)}
|
|
17
|
+
onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
|
|
18
|
+
onDragLeave={() => setDrag(false)}
|
|
19
|
+
onDrop={(e) => { e.preventDefault(); setDrag(false); pick(e.dataTransfer.files); }}
|
|
20
|
+
>
|
|
21
|
+
<span className="cs-dropzone__icon">
|
|
22
|
+
{icon ?? <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 16V4M7 9l5-5 5 5" /><path d="M5 16v3a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3" /></svg>}
|
|
23
|
+
</span>
|
|
24
|
+
<span className="cs-dropzone__title">{tt}</span>
|
|
25
|
+
<span className="cs-dropzone__hint">{hh}</span>
|
|
26
|
+
<input type="file" accept={accept} multiple={multiple} style={{ display: "none" }} onChange={(e) => pick(e.target.files)} />
|
|
27
|
+
</label>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/** One validation rule: "required" (bilingual default message) or fn(value, values) → message | null. */
|
|
4
|
+
export type FormRule = "required" | ((value: unknown, values: Record<string, unknown>) => string | null | undefined);
|
|
5
|
+
|
|
6
|
+
/** Semantic form + optional controller. Plain mode: named native fields collected via
|
|
7
|
+
* FormData into onSubmit(values); `errors` renders the bilingual summary. Controller mode:
|
|
8
|
+
* `rules` validate on submit (blocking until clean); FormField children with `name`
|
|
9
|
+
* auto-wire value/onChange + per-field errors via context. Dotted paths work with FormFieldArray. */
|
|
10
|
+
export interface FormProps {
|
|
11
|
+
onSubmit?: (values: Record<string, unknown>) => void;
|
|
12
|
+
/** External errors (name → message); merged over rule errors in summary + fields. */
|
|
13
|
+
errors?: Record<string, string | undefined>;
|
|
14
|
+
/** name → rule or rule[]; validated on submit. */
|
|
15
|
+
rules?: Record<string, FormRule | FormRule[]>;
|
|
16
|
+
/** name → async (value, values) => message | null; runs after sync rules pass. */
|
|
17
|
+
asyncRules?: Record<string, (value: unknown, values: Record<string, unknown>) => Promise<string | null | undefined>>;
|
|
18
|
+
/** Seed for controller-registered fields. */
|
|
19
|
+
initialValues?: Record<string, unknown>;
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
lang?: string;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export function Form(props: FormProps): React.ReactElement;
|
|
25
|
+
|
|
26
|
+
/** Label + control + hint/error line. With `name` inside a Form, registers with the
|
|
27
|
+
* controller: single element child cloned with value/onChange (valueProp="checked"
|
|
28
|
+
* for checkbox-shaped children); context error auto-shows (explicit `error` wins). */
|
|
29
|
+
export interface FormFieldProps {
|
|
30
|
+
label: ReactNode;
|
|
31
|
+
/** Register with the surrounding Form controller under this key (supports dotted paths). */
|
|
32
|
+
name?: string;
|
|
33
|
+
required?: boolean;
|
|
34
|
+
hint?: ReactNode;
|
|
35
|
+
error?: ReactNode;
|
|
36
|
+
/** Prop carrying the value on the child ("value" default; "checked" for Checkbox/Switch/Toggle). */
|
|
37
|
+
valueProp?: "value" | "checked";
|
|
38
|
+
children?: ReactNode;
|
|
39
|
+
lang?: string;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
export function FormField(props: FormFieldProps): React.ReactElement;
|
|
43
|
+
|
|
44
|
+
export interface FormFieldArrayRenderArgs {
|
|
45
|
+
index: number;
|
|
46
|
+
item: Record<string, unknown>;
|
|
47
|
+
remove: () => void;
|
|
48
|
+
/** Build a dotted field path under this row, e.g. path("name") → teammates.0.name */
|
|
49
|
+
path: (field: string) => string;
|
|
50
|
+
}
|
|
51
|
+
export interface FormFieldArrayProps {
|
|
52
|
+
name: string;
|
|
53
|
+
label?: ReactNode;
|
|
54
|
+
children: (args: FormFieldArrayRenderArgs) => ReactNode;
|
|
55
|
+
min?: number;
|
|
56
|
+
max?: number;
|
|
57
|
+
addLabel?: ReactNode;
|
|
58
|
+
defaultItem?: Record<string, unknown> | (() => Record<string, unknown>);
|
|
59
|
+
className?: string;
|
|
60
|
+
lang?: string;
|
|
61
|
+
}
|
|
62
|
+
export function FormFieldArray(props: FormFieldArrayProps): React.ReactElement;
|
|
63
|
+
|
|
64
|
+
export interface FormWizardStep {
|
|
65
|
+
id?: string;
|
|
66
|
+
title?: ReactNode;
|
|
67
|
+
rules?: Record<string, FormRule | FormRule[]>;
|
|
68
|
+
render: (ctx: {
|
|
69
|
+
values: Record<string, unknown>;
|
|
70
|
+
step: number;
|
|
71
|
+
setValue: (name: string, value: unknown) => void;
|
|
72
|
+
}) => ReactNode;
|
|
73
|
+
}
|
|
74
|
+
export interface FormWizardProps {
|
|
75
|
+
steps: FormWizardStep[];
|
|
76
|
+
initialValues?: Record<string, unknown>;
|
|
77
|
+
onComplete?: (values: Record<string, unknown>) => void;
|
|
78
|
+
lang?: string;
|
|
79
|
+
className?: string;
|
|
80
|
+
nextLabel?: ReactNode;
|
|
81
|
+
backLabel?: ReactNode;
|
|
82
|
+
finishLabel?: ReactNode;
|
|
83
|
+
}
|
|
84
|
+
export function FormWizard(props: FormWizardProps): React.ReactElement;
|
|
85
|
+
|
|
86
|
+
export function getPath(obj: unknown, path: string): unknown;
|
|
87
|
+
export function setPath(obj: unknown, path: string, value: unknown): unknown;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import figma from '@figma/code-connect'
|
|
2
|
+
import { Form } from './Form.jsx'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Code Connect stub — Form
|
|
6
|
+
* Prop maps stay minimal until the matching Figma library component is published;
|
|
7
|
+
* then set nodeId in code-connect/node-map.json and re-run generate-code-connect.
|
|
8
|
+
*/
|
|
9
|
+
figma.connect(Form, 'https://www.figma.com/design/CS_FIGMA_FILE_KEY/CyberSkill?node-id=9999-38', {
|
|
10
|
+
example: () => <Form />,
|
|
11
|
+
imports: ["import { Form } from '@cyberskill/design'"],
|
|
12
|
+
})
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
|
+
import { cx } from "../_utils/cx.js";
|
|
4
|
+
|
|
5
|
+
// Lazy context — bundle evaluates modules before React is loaded on some gate pages.
|
|
6
|
+
let FormCtx;
|
|
7
|
+
function getFormCtx() {
|
|
8
|
+
if (!FormCtx) FormCtx = React.createContext(null);
|
|
9
|
+
return FormCtx;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Read a dotted path (supports array indices as numeric segments). */
|
|
13
|
+
export function getPath(obj, path) {
|
|
14
|
+
if (!path) return undefined;
|
|
15
|
+
const parts = String(path).split(".");
|
|
16
|
+
let cur = obj;
|
|
17
|
+
for (const p of parts) {
|
|
18
|
+
if (cur == null) return undefined;
|
|
19
|
+
cur = cur[p];
|
|
20
|
+
}
|
|
21
|
+
return cur;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Immutable set on a dotted path; creates objects/arrays as needed. */
|
|
25
|
+
export function setPath(obj, path, value) {
|
|
26
|
+
const parts = String(path).split(".");
|
|
27
|
+
const root = Array.isArray(obj) ? [...obj] : { ...(obj || {}) };
|
|
28
|
+
let cur = root;
|
|
29
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
30
|
+
const p = parts[i];
|
|
31
|
+
const nextKey = parts[i + 1];
|
|
32
|
+
const nextIsIndex = /^\d+$/.test(nextKey);
|
|
33
|
+
const existing = cur[p];
|
|
34
|
+
const clone = existing == null
|
|
35
|
+
? (nextIsIndex ? [] : {})
|
|
36
|
+
: (Array.isArray(existing) ? [...existing] : { ...existing });
|
|
37
|
+
cur[p] = clone;
|
|
38
|
+
cur = clone;
|
|
39
|
+
}
|
|
40
|
+
cur[parts[parts.length - 1]] = value;
|
|
41
|
+
return root;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* CyberSkill Form — semantic form + optional controller (v3.7).
|
|
46
|
+
* Plain mode (unchanged): named native fields are collected via FormData into onSubmit(values);
|
|
47
|
+
* `errors` renders the bilingual summary. Controller mode: pass `rules` (name → "required" |
|
|
48
|
+
* fn(value, values) => msg|null | array of those); FormField children with `name` register via
|
|
49
|
+
* context — value/onChange auto-wired, per-field errors auto-shown, submit blocked until clean.
|
|
50
|
+
* Dotted names (e.g. teammates.0.name) work with FormFieldArray.
|
|
51
|
+
*/
|
|
52
|
+
export function Form({ onSubmit, errors = {}, rules, asyncRules, initialValues, children, lang, className, ...props }) {
|
|
53
|
+
const [ref, L] = useLang(lang);
|
|
54
|
+
const t = makeT("Form", L);
|
|
55
|
+
const [values, setValues] = React.useState(() => initialValues || {});
|
|
56
|
+
const [ruleErrors, setRuleErrors] = React.useState({});
|
|
57
|
+
const [pending, setPending] = React.useState(false);
|
|
58
|
+
const setValue = React.useCallback((name, v) => {
|
|
59
|
+
setValues((s) => (String(name).includes(".") ? setPath(s, name, v) : { ...s, [name]: v }));
|
|
60
|
+
setRuleErrors((e) => (e[name] ? { ...e, [name]: undefined } : e));
|
|
61
|
+
}, []);
|
|
62
|
+
const merged = { ...ruleErrors, ...errors };
|
|
63
|
+
const keys = Object.keys(merged).filter((k) => merged[k]);
|
|
64
|
+
const runRules = (v, ruleMap) => {
|
|
65
|
+
const map = ruleMap || rules;
|
|
66
|
+
if (!map) return {};
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const [name, r] of Object.entries(map)) {
|
|
69
|
+
for (const rule of (Array.isArray(r) ? r : [r])) {
|
|
70
|
+
const fieldVal = String(name).includes(".") ? getPath(v, name) : v[name];
|
|
71
|
+
const msg = rule === "required"
|
|
72
|
+
? ((fieldVal == null || String(fieldVal).trim() === "") ? t("requiredField") : null)
|
|
73
|
+
: (typeof rule === "function" ? rule(fieldVal, v) : null);
|
|
74
|
+
if (msg) { out[name] = msg; break; }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
};
|
|
79
|
+
const runAsyncRules = async (v) => {
|
|
80
|
+
if (!asyncRules) return {};
|
|
81
|
+
const out = {};
|
|
82
|
+
for (const [name, fn] of Object.entries(asyncRules)) {
|
|
83
|
+
if (typeof fn !== "function") continue;
|
|
84
|
+
try {
|
|
85
|
+
const fieldVal = String(name).includes(".") ? getPath(v, name) : v[name];
|
|
86
|
+
const msg = await fn(fieldVal, v);
|
|
87
|
+
if (msg) out[name] = msg;
|
|
88
|
+
} catch (e) {
|
|
89
|
+
out[name] = String(e && e.message || e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
};
|
|
94
|
+
const ctx = { values, setValue, setValues, errors: merged, pending, runRules, setRuleErrors, t, L };
|
|
95
|
+
const Ctx = getFormCtx();
|
|
96
|
+
return (
|
|
97
|
+
<Ctx.Provider value={ctx}>
|
|
98
|
+
<form {...props} ref={ref} className={cx("cs-form", pending && "is-pending", className)} noValidate
|
|
99
|
+
onSubmit={async (e) => {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
const fd = new FormData(e.currentTarget);
|
|
102
|
+
const v = {}; fd.forEach((val, k) => { v[k] = val; });
|
|
103
|
+
Object.assign(v, values); // controller-registered fields are the source of truth
|
|
104
|
+
const errs = runRules(v);
|
|
105
|
+
if (Object.keys(errs).some((k) => errs[k])) { setRuleErrors(errs); return; }
|
|
106
|
+
setPending(true);
|
|
107
|
+
try {
|
|
108
|
+
const aerrs = await runAsyncRules(v);
|
|
109
|
+
setRuleErrors(aerrs);
|
|
110
|
+
if (Object.keys(aerrs).some((k) => aerrs[k])) return;
|
|
111
|
+
onSubmit && onSubmit(v);
|
|
112
|
+
} finally { setPending(false); }
|
|
113
|
+
}}>
|
|
114
|
+
{keys.length ? (
|
|
115
|
+
<div className="cs-form__summary" role="alert">
|
|
116
|
+
<b>{t("summary")}</b>
|
|
117
|
+
<ul>{keys.map((k) => <li key={k}>{merged[k]}</li>)}</ul>
|
|
118
|
+
</div>
|
|
119
|
+
) : null}
|
|
120
|
+
{children}
|
|
121
|
+
</form>
|
|
122
|
+
</Ctx.Provider>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* CyberSkill FormField — label + control + hint/error line. With `name` inside a Form,
|
|
128
|
+
* it registers with the controller: the single element child is cloned with value/onChange
|
|
129
|
+
* (set valueProp="checked" for Checkbox/Switch/Toggle-shaped children) and the field's
|
|
130
|
+
* context error shows automatically (an explicit `error` prop still wins).
|
|
131
|
+
*/
|
|
132
|
+
export function FormField({ label, name, required = false, hint, error, valueProp = "value", children, lang, className }) {
|
|
133
|
+
const [ref, L] = useLang(lang);
|
|
134
|
+
const t = makeT("Form", L);
|
|
135
|
+
const ctx = React.useContext(getFormCtx());
|
|
136
|
+
const err = error !== undefined && error !== null ? error : (name && ctx ? ctx.errors[name] : undefined);
|
|
137
|
+
let child = children;
|
|
138
|
+
if (name && ctx && React.isValidElement(children) && React.Children.count(children) === 1) {
|
|
139
|
+
const cur = String(name).includes(".") ? getPath(ctx.values, name) : ctx.values[name];
|
|
140
|
+
const wire = { name };
|
|
141
|
+
wire[valueProp] = cur !== undefined ? cur : (valueProp === "checked" ? false : "");
|
|
142
|
+
wire.onChange = (ev) => {
|
|
143
|
+
const val = ev && ev.target ? (valueProp === "checked" ? ev.target.checked : ev.target.value) : ev;
|
|
144
|
+
ctx.setValue(name, val);
|
|
145
|
+
if (children.props.onChange) children.props.onChange(ev);
|
|
146
|
+
};
|
|
147
|
+
child = React.cloneElement(children, wire);
|
|
148
|
+
}
|
|
149
|
+
return (
|
|
150
|
+
<label ref={ref} className={cx("cs-formfield", err && "has-error", className)}>
|
|
151
|
+
<span className="cs-formfield__label">{label}{required ? <em aria-label={t("required")}> *</em> : null}</span>
|
|
152
|
+
{child}
|
|
153
|
+
{err ? <span className="cs-formfield__error" role="alert">{err}</span> : hint ? <span className="cs-formfield__hint">{hint}</span> : null}
|
|
154
|
+
</label>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* FormFieldArray — manage an array of row objects under `name` in the surrounding Form.
|
|
160
|
+
* children: ({ index, item, remove, path }) => ReactNode
|
|
161
|
+
*/
|
|
162
|
+
export function FormFieldArray({
|
|
163
|
+
name,
|
|
164
|
+
children,
|
|
165
|
+
label,
|
|
166
|
+
min = 0,
|
|
167
|
+
max = 50,
|
|
168
|
+
addLabel,
|
|
169
|
+
defaultItem,
|
|
170
|
+
className,
|
|
171
|
+
lang,
|
|
172
|
+
}) {
|
|
173
|
+
const [ref, L] = useLang(lang);
|
|
174
|
+
const t = makeT("Form", L);
|
|
175
|
+
const ctx = React.useContext(getFormCtx());
|
|
176
|
+
if (!ctx) {
|
|
177
|
+
return <div className="cs-formfield__error" role="alert">FormFieldArray must be used inside Form</div>;
|
|
178
|
+
}
|
|
179
|
+
const list = Array.isArray(getPath(ctx.values, name)) ? getPath(ctx.values, name) : [];
|
|
180
|
+
const blank = () => (defaultItem != null ? (typeof defaultItem === "function" ? defaultItem() : { ...defaultItem }) : {});
|
|
181
|
+
const setList = (next) => ctx.setValue(name, next);
|
|
182
|
+
const add = () => {
|
|
183
|
+
if (list.length >= max) return;
|
|
184
|
+
setList([...list, blank()]);
|
|
185
|
+
};
|
|
186
|
+
const removeAt = (i) => {
|
|
187
|
+
if (list.length <= min) return;
|
|
188
|
+
setList(list.filter((_, idx) => idx !== i));
|
|
189
|
+
};
|
|
190
|
+
return (
|
|
191
|
+
<div ref={ref} className={cx("cs-form-array", className)} data-name={name}>
|
|
192
|
+
{label ? <div className="cs-formfield__label" style={{ marginBottom: 8 }}>{label}</div> : null}
|
|
193
|
+
<div className="cs-form-array__rows">
|
|
194
|
+
{list.map((item, index) => (
|
|
195
|
+
<div className="cs-form-array__row" key={index} data-index={index}>
|
|
196
|
+
{typeof children === "function"
|
|
197
|
+
? children({
|
|
198
|
+
index,
|
|
199
|
+
item,
|
|
200
|
+
remove: () => removeAt(index),
|
|
201
|
+
path: (field) => `${name}.${index}.${field}`,
|
|
202
|
+
})
|
|
203
|
+
: children}
|
|
204
|
+
</div>
|
|
205
|
+
))}
|
|
206
|
+
</div>
|
|
207
|
+
<button
|
|
208
|
+
type="button"
|
|
209
|
+
className="cs-button cs-button--secondary cs-button--sm"
|
|
210
|
+
onClick={add}
|
|
211
|
+
disabled={list.length >= max}
|
|
212
|
+
style={{ marginTop: 8 }}
|
|
213
|
+
>
|
|
214
|
+
{addLabel || (L === "vi" ? "Thêm dòng" : "Add row")}
|
|
215
|
+
</button>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* FormWizard — multi-step controller wrapping Form context without a nested <form>.
|
|
222
|
+
* Each step may declare `rules` and a `render()` body of FormFields.
|
|
223
|
+
*/
|
|
224
|
+
export function FormWizard({
|
|
225
|
+
steps = [],
|
|
226
|
+
initialValues,
|
|
227
|
+
onComplete,
|
|
228
|
+
lang,
|
|
229
|
+
className,
|
|
230
|
+
nextLabel,
|
|
231
|
+
backLabel,
|
|
232
|
+
finishLabel,
|
|
233
|
+
}) {
|
|
234
|
+
const [ref, L] = useLang(lang);
|
|
235
|
+
const t = makeT("Form", L);
|
|
236
|
+
const [step, setStep] = React.useState(0);
|
|
237
|
+
const [values, setValues] = React.useState(() => initialValues || {});
|
|
238
|
+
const [ruleErrors, setRuleErrors] = React.useState({});
|
|
239
|
+
const [pending, setPending] = React.useState(false);
|
|
240
|
+
const setValue = React.useCallback((name, v) => {
|
|
241
|
+
setValues((s) => (String(name).includes(".") ? setPath(s, name, v) : { ...s, [name]: v }));
|
|
242
|
+
setRuleErrors((e) => (e[name] ? { ...e, [name]: undefined } : e));
|
|
243
|
+
}, []);
|
|
244
|
+
const runRules = React.useCallback((v, ruleMap) => {
|
|
245
|
+
if (!ruleMap) return {};
|
|
246
|
+
const out = {};
|
|
247
|
+
for (const [name, r] of Object.entries(ruleMap)) {
|
|
248
|
+
for (const rule of (Array.isArray(r) ? r : [r])) {
|
|
249
|
+
const fieldVal = String(name).includes(".") ? getPath(v, name) : v[name];
|
|
250
|
+
const msg = rule === "required"
|
|
251
|
+
? ((fieldVal == null || String(fieldVal).trim() === "") ? t("requiredField") : null)
|
|
252
|
+
: (typeof rule === "function" ? rule(fieldVal, v) : null);
|
|
253
|
+
if (msg) { out[name] = msg; break; }
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}, [t]);
|
|
258
|
+
const current = steps[step] || {};
|
|
259
|
+
const ctx = { values, setValue, setValues, errors: ruleErrors, pending, runRules, setRuleErrors, t, L };
|
|
260
|
+
const keys = Object.keys(ruleErrors).filter((k) => ruleErrors[k]);
|
|
261
|
+
const goNext = async () => {
|
|
262
|
+
const errs = runRules(values, current.rules);
|
|
263
|
+
if (Object.keys(errs).some((k) => errs[k])) { setRuleErrors(errs); return; }
|
|
264
|
+
setRuleErrors({});
|
|
265
|
+
if (step >= steps.length - 1) {
|
|
266
|
+
setPending(true);
|
|
267
|
+
try { onComplete && onComplete(values); }
|
|
268
|
+
finally { setPending(false); }
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
setStep((s) => s + 1);
|
|
272
|
+
};
|
|
273
|
+
const goBack = () => {
|
|
274
|
+
setRuleErrors({});
|
|
275
|
+
setStep((s) => Math.max(0, s - 1));
|
|
276
|
+
};
|
|
277
|
+
const Ctx = getFormCtx();
|
|
278
|
+
return (
|
|
279
|
+
<Ctx.Provider value={ctx}>
|
|
280
|
+
<div ref={ref} className={cx("cs-form-wizard", className)} data-step={step}>
|
|
281
|
+
<ol className="cs-form-wizard__steps" style={{ display: "flex", gap: 10, listStyle: "none", padding: 0, margin: "0 0 16px", flexWrap: "wrap" }}>
|
|
282
|
+
{steps.map((s, i) => (
|
|
283
|
+
<li key={s.id || i} style={{
|
|
284
|
+
font: "700 11px/1 var(--cs-font-family-ui)",
|
|
285
|
+
textTransform: "uppercase",
|
|
286
|
+
letterSpacing: ".06em",
|
|
287
|
+
color: i === step ? "var(--cs-color-brand-umber)" : "var(--cs-color-text-primary)",
|
|
288
|
+
opacity: i === step ? 1 : 0.55,
|
|
289
|
+
}}>
|
|
290
|
+
{i + 1}. {s.title || s.id || `Step ${i + 1}`}
|
|
291
|
+
</li>
|
|
292
|
+
))}
|
|
293
|
+
</ol>
|
|
294
|
+
{keys.length ? (
|
|
295
|
+
<div className="cs-form__summary" role="alert">
|
|
296
|
+
<b>{t("summary")}</b>
|
|
297
|
+
<ul>{keys.map((k) => <li key={k}>{ruleErrors[k]}</li>)}</ul>
|
|
298
|
+
</div>
|
|
299
|
+
) : null}
|
|
300
|
+
<div className="cs-form-wizard__body">
|
|
301
|
+
{typeof current.render === "function" ? current.render({ values, step, setValue }) : null}
|
|
302
|
+
</div>
|
|
303
|
+
<div className="cs-form-wizard__nav" style={{ display: "flex", gap: 10, marginTop: 16 }}>
|
|
304
|
+
<button type="button" className="cs-button cs-button--secondary cs-button--sm" onClick={goBack} disabled={step === 0 || pending}>
|
|
305
|
+
{backLabel || (L === "vi" ? "Quay lại" : "Back")}
|
|
306
|
+
</button>
|
|
307
|
+
<button type="button" className="cs-button cs-button--sm" onClick={goNext} disabled={pending}>
|
|
308
|
+
{step >= steps.length - 1
|
|
309
|
+
? (finishLabel || (L === "vi" ? "Hoàn tất" : "Finish"))
|
|
310
|
+
: (nextLabel || (L === "vi" ? "Tiếp" : "Next"))}
|
|
311
|
+
</button>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
</Ctx.Provider>
|
|
315
|
+
);
|
|
316
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
**Form + FormField** — named-field collection + bilingual error summary; optional controller: `rules` validate on submit, `name`d FormFields auto-wire value/onChange + per-field errors. Dotted names work with field arrays (e.g. `teammates.0.name`).
|
|
2
|
+
|
|
3
|
+
```jsx
|
|
4
|
+
<Form rules={{email:["required", v=>/.+@.+/.test(v)?null:"Enter a valid email."]}} onSubmit={save}>
|
|
5
|
+
<FormField label="Work email" required name="email"><TextField label="Work email"/></FormField>
|
|
6
|
+
<FormField label="Đồng ý" name="agree" valueProp="checked"><Checkbox label="Đồng ý điều khoản"/></FormField>
|
|
7
|
+
<Button type="submit">Send</Button>
|
|
8
|
+
</Form>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Manual mode unchanged: omit `rules`/`name`, pass `errors={{email:"…"}}` yourself.
|
|
12
|
+
|
|
13
|
+
**asyncRules:** optional map of field name → async `(value, values) => message|null`. Runs after sync `rules` pass; blocks submit while pending.
|
|
14
|
+
|
|
15
|
+
**FormFieldArray** — manage an array of row objects under `name` on the surrounding Form. Children render-prop: `({ index, item, remove, path })`.
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
<Form initialValues={{teammates:[{name:""}]}} onSubmit={save}>
|
|
19
|
+
<FormFieldArray name="teammates" label="Teammates" min={1} max={5} addLabel="Add person">
|
|
20
|
+
{({ index, remove, path }) => (
|
|
21
|
+
<>
|
|
22
|
+
<FormField label={`Name ${index+1}`} name={path("name")}><TextField label="Name"/></FormField>
|
|
23
|
+
<Button type="button" variant="ghost" size="sm" onClick={remove}>Remove</Button>
|
|
24
|
+
</>
|
|
25
|
+
)}
|
|
26
|
+
</FormFieldArray>
|
|
27
|
+
<Button type="submit">Save</Button>
|
|
28
|
+
</Form>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**FormWizard** — multi-step controller (no nested `<form>`). Each step may declare `rules` + `render()`. Finish calls `onComplete(values)`.
|
|
32
|
+
|
|
33
|
+
```jsx
|
|
34
|
+
<FormWizard
|
|
35
|
+
initialValues={{email:"",wish:""}}
|
|
36
|
+
onComplete={save}
|
|
37
|
+
steps={[
|
|
38
|
+
{id:"contact", title:"Contact", rules:{email:"required"},
|
|
39
|
+
render:()=><FormField label="Email" required name="email"><TextField label="Email"/></FormField>},
|
|
40
|
+
{id:"wish", title:"Wish", rules:{wish:"required"},
|
|
41
|
+
render:()=><FormField label="Wish" required name="wish"><TextField label="Wish"/></FormField>},
|
|
42
|
+
]}
|
|
43
|
+
/>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Helpers `getPath` / `setPath` support dotted paths (including numeric array segments). Must be used inside Form context (FormFieldArray) or FormWizard.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Click-to-edit text: view button ⇄ input. Enter/blur commits, Escape cancels.
|
|
2
|
+
* Controlled (value/onChange) or uncontrolled. Bilingual edit/empty labels. */
|
|
3
|
+
export interface InlineEditProps {
|
|
4
|
+
value?: string;
|
|
5
|
+
defaultValue?: string;
|
|
6
|
+
onChange?: (value: string) => void;
|
|
7
|
+
/** Accessible field name (appended to the edit label). */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
10
|
+
lang?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
export function InlineEdit(props: InlineEditProps): React.ReactElement;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import figma from '@figma/code-connect'
|
|
2
|
+
import { InlineEdit } from './InlineEdit.jsx'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Code Connect stub — InlineEdit
|
|
6
|
+
* Prop maps stay minimal until the matching Figma library component is published;
|
|
7
|
+
* then set nodeId in code-connect/node-map.json and re-run generate-code-connect.
|
|
8
|
+
*/
|
|
9
|
+
figma.connect(InlineEdit, 'https://www.figma.com/design/CS_FIGMA_FILE_KEY/CyberSkill?node-id=9999-44', {
|
|
10
|
+
example: () => <InlineEdit />,
|
|
11
|
+
imports: ["import { InlineEdit } from '@cyberskill/design'"],
|
|
12
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
|
+
import { cx } from "../_utils/cx.js";
|
|
4
|
+
const PEN = <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M4 20l4.5-.9L20 7.6a2 2 0 0 0-2.8-2.8L5.7 16.3 4 20z" /></svg>;
|
|
5
|
+
|
|
6
|
+
/** CyberSkill InlineEdit — click-to-edit text. Enter/blur commits, Escape cancels. */
|
|
7
|
+
export function InlineEdit({ value, defaultValue = "", onChange, label, lang, className }) {
|
|
8
|
+
const [inner, setInner] = React.useState(defaultValue);
|
|
9
|
+
const val = value != null ? value : inner;
|
|
10
|
+
const [edit, setEdit] = React.useState(false);
|
|
11
|
+
const [draft, setDraft] = React.useState(val);
|
|
12
|
+
const commit = () => { setEdit(false); if (draft !== val) { if (value == null) setInner(draft); onChange && onChange(draft); } };
|
|
13
|
+
const [ref, L] = useLang(lang);
|
|
14
|
+
const t = makeT("InlineEdit", L);
|
|
15
|
+
return (
|
|
16
|
+
<span ref={ref} className={cx("cs-inline-edit", className)}>
|
|
17
|
+
{edit ? (
|
|
18
|
+
<input autoFocus value={draft} aria-label={label} onChange={(e) => setDraft(e.target.value)} onBlur={commit}
|
|
19
|
+
onKeyDown={(e) => { if (e.key === "Enter") commit(); else if (e.key === "Escape") { setDraft(val); setEdit(false); } }} />
|
|
20
|
+
) : (
|
|
21
|
+
<button type="button" className="cs-inline-edit__view" aria-label={t("edit") + (label ? ": " + label : "")} onClick={() => { setDraft(val); setEdit(true); }}>
|
|
22
|
+
<span className={val ? undefined : "ph"}>{val || t("empty")}</span>{PEN}
|
|
23
|
+
</button>
|
|
24
|
+
)}
|
|
25
|
+
</span>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/** Input with prefix/suffix addons (text or nodes), a clearable ×, and a
|
|
4
|
+
* password show/hide reveal. Controlled or uncontrolled. */
|
|
5
|
+
export interface InputGroupProps {
|
|
6
|
+
prefix?: ReactNode;
|
|
7
|
+
suffix?: ReactNode;
|
|
8
|
+
clearable?: boolean;
|
|
9
|
+
/** Renders a password field with a reveal button. */
|
|
10
|
+
password?: boolean;
|
|
11
|
+
value?: string;
|
|
12
|
+
defaultValue?: string;
|
|
13
|
+
onChange?: (value: string) => void;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
17
|
+
lang?: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export function InputGroup(props: InputGroupProps): React.ReactElement;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import figma from '@figma/code-connect'
|
|
2
|
+
import { InputGroup } from './InputGroup.jsx'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Code Connect stub — InputGroup
|
|
6
|
+
* Prop maps stay minimal until the matching Figma library component is published;
|
|
7
|
+
* then set nodeId in code-connect/node-map.json and re-run generate-code-connect.
|
|
8
|
+
*/
|
|
9
|
+
figma.connect(InputGroup, 'https://www.figma.com/design/CS_FIGMA_FILE_KEY/CyberSkill?node-id=9999-45', {
|
|
10
|
+
example: () => <InputGroup />,
|
|
11
|
+
imports: ["import { InputGroup } from '@cyberskill/design'"],
|
|
12
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { makeT, useLang } from "../_i18n/i18n.js";
|
|
3
|
+
import { cx } from "../_utils/cx.js";
|
|
4
|
+
const EYE = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/></svg>;
|
|
5
|
+
const EYE_OFF = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z"/><circle cx="12" cy="12" r="3"/><path d="M4 4l16 16"/></svg>;
|
|
6
|
+
const X = <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>;
|
|
7
|
+
|
|
8
|
+
/** CyberSkill InputGroup — input with prefix/suffix addons, clearable ×, and password reveal. */
|
|
9
|
+
export function InputGroup({ prefix, suffix, clearable = false, password = false, value, onChange, defaultValue = "", placeholder, disabled = false, lang, className, ...props }) {
|
|
10
|
+
const [inner, setInner] = React.useState(defaultValue);
|
|
11
|
+
const val = value != null ? value : inner;
|
|
12
|
+
const set = (v) => { if (value == null) setInner(v); onChange && onChange(v); };
|
|
13
|
+
const [show, setShow] = React.useState(false);
|
|
14
|
+
const [ref, L] = useLang(lang);
|
|
15
|
+
const t = makeT("InputGroup", L);
|
|
16
|
+
return (
|
|
17
|
+
<span ref={ref} className={cx("cs-igroup", className)}>
|
|
18
|
+
{prefix != null ? <span className="cs-igroup__fix">{prefix}</span> : null}
|
|
19
|
+
<input {...props} type={password && !show ? "password" : "text"} value={val} placeholder={placeholder} disabled={disabled} onChange={(e) => set(e.target.value)} />
|
|
20
|
+
{clearable && String(val).length ? <button type="button" className="cs-igroup__btn" aria-label={t("clear")} onClick={() => set("")}>{X}</button> : null}
|
|
21
|
+
{password ? <button type="button" className="cs-igroup__btn" aria-label={show ? t("hide") : t("show")} aria-pressed={show} onClick={() => setShow((s) => !s)}>{show ? EYE_OFF : EYE}</button> : null}
|
|
22
|
+
{suffix != null ? <span className="cs-igroup__fix cs-igroup__fix--suffix">{suffix}</span> : null}
|
|
23
|
+
</span>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
**InputGroup** — input with prefix/suffix addons, clearable ×, password reveal. Bilingual button labels via the registry.
|
|
2
|
+
|
|
3
|
+
```jsx
|
|
4
|
+
<InputGroup prefix="https://" suffix=".world" defaultValue="cyberskill" clearable/>
|
|
5
|
+
<InputGroup password placeholder="Password"/>
|
|
6
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** One-time-code input: N digit boxes with auto-advance, backspace and paste.
|
|
2
|
+
* Controlled (value/onChange) or uncontrolled. onComplete fires at full length. */
|
|
3
|
+
export interface InputOTPProps {
|
|
4
|
+
/** Box count. Default 6. */
|
|
5
|
+
length?: number;
|
|
6
|
+
value?: string;
|
|
7
|
+
onChange?: (code: string) => void;
|
|
8
|
+
onComplete?: (code: string) => void;
|
|
9
|
+
/** Accessible label. Default from the bilingual registry ("One-time code" / "Mã dùng một lần"). */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** "en" | "vi" — else resolved from the nearest [lang] ancestor (vi default). */
|
|
12
|
+
lang?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
export function InputOTP(props: InputOTPProps): React.ReactElement;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import figma from '@figma/code-connect'
|
|
2
|
+
import { InputOTP } from './InputOTP.jsx'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Code Connect stub — InputOTP
|
|
6
|
+
* Prop maps stay minimal until the matching Figma library component is published;
|
|
7
|
+
* then set nodeId in code-connect/node-map.json and re-run generate-code-connect.
|
|
8
|
+
*/
|
|
9
|
+
figma.connect(InputOTP, 'https://www.figma.com/design/CS_FIGMA_FILE_KEY/CyberSkill?node-id=9999-46', {
|
|
10
|
+
example: () => <InputOTP />,
|
|
11
|
+
imports: ["import { InputOTP } from '@cyberskill/design'"],
|
|
12
|
+
})
|