@devalok/shilp-sutra 0.49.3 → 0.49.5
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/_chunks/badge-group.js +8 -7
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/block-shell.js.map +1 -1
- package/dist/_chunks/chart-container.js.map +1 -1
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/colors.js.map +1 -1
- package/dist/_chunks/document-preview.js.map +1 -1
- package/dist/_chunks/emoji-suggestion.js.map +1 -1
- package/dist/_chunks/emoji.js +2 -2
- package/dist/_chunks/emoji.js.map +1 -1
- package/dist/_chunks/field-state.js.map +1 -1
- package/dist/_chunks/grid-lines.js.map +1 -1
- package/dist/_chunks/image-preview.js.map +1 -1
- package/dist/_chunks/keybinding.js.map +1 -1
- package/dist/_chunks/link-context.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/normalize-icon.js.map +1 -1
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/primitives.js +1123 -1153
- package/dist/_chunks/primitives.js.map +1 -1
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/success.js.map +1 -1
- package/dist/_chunks/tiptap.js +4283 -3460
- package/dist/_chunks/tiptap.js.map +1 -1
- package/dist/_chunks/tooltip.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/_chunks/use-calendar.js.map +1 -1
- package/dist/_chunks/use-controllable-open.js.map +1 -1
- package/dist/_chunks/vendor-client.js +86 -59
- package/dist/_chunks/vendor-client.js.map +1 -1
- package/dist/_chunks/vendor-utils.js +555 -513
- package/dist/_chunks/vendor-utils.js.map +1 -1
- package/dist/ai/ai-command-provider.d.ts +1 -1
- package/dist/ai/ai-command-provider.d.ts.map +1 -1
- package/dist/ai/ai-command-provider.js.map +1 -1
- package/dist/ai/block-renderer.js.map +1 -1
- package/dist/ai/blocks/block-shell.d.ts +1 -1
- package/dist/ai/blocks/block-shell.d.ts.map +1 -1
- package/dist/ai/blocks/block-table.d.ts +1 -1
- package/dist/ai/blocks/block-table.d.ts.map +1 -1
- package/dist/ai/blocks/confirm.d.ts +1 -1
- package/dist/ai/blocks/confirm.d.ts.map +1 -1
- package/dist/ai/blocks/divider.d.ts +1 -1
- package/dist/ai/blocks/divider.d.ts.map +1 -1
- package/dist/ai/blocks/error.d.ts +1 -1
- package/dist/ai/blocks/error.d.ts.map +1 -1
- package/dist/ai/blocks/error.js.map +1 -1
- package/dist/ai/blocks/info.d.ts +1 -1
- package/dist/ai/blocks/info.d.ts.map +1 -1
- package/dist/ai/blocks/loading.d.ts +1 -1
- package/dist/ai/blocks/loading.d.ts.map +1 -1
- package/dist/ai/blocks/stat-row.d.ts +1 -1
- package/dist/ai/blocks/stat-row.d.ts.map +1 -1
- package/dist/ai/blocks/success.d.ts +1 -1
- package/dist/ai/blocks/success.d.ts.map +1 -1
- package/dist/ai/blocks/text.d.ts +1 -1
- package/dist/ai/blocks/text.d.ts.map +1 -1
- package/dist/ai/blocks/text.js.map +1 -1
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/devadoot-icon.d.ts +1 -1
- package/dist/ai/devadoot-icon.d.ts.map +1 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/avatar-group.js.map +1 -1
- package/dist/composed/bulk-action-bar.js.map +1 -1
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/confirm-dialog.js.map +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js.map +1 -1
- package/dist/composed/deadline-indicator.js.map +1 -1
- package/dist/composed/emoji-picker.d.ts +2 -2
- package/dist/composed/emoji-picker.d.ts.map +1 -1
- package/dist/composed/emoji-picker.js.map +1 -1
- package/dist/composed/empty-state.js.map +1 -1
- package/dist/composed/error-boundary.d.ts +1 -1
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/extensions/emoji-node.js.map +1 -1
- package/dist/composed/file-preview/audio-preview.d.ts +2 -1
- package/dist/composed/file-preview/audio-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/document-preview.d.ts +2 -1
- package/dist/composed/file-preview/document-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/embed-preview.d.ts +2 -1
- package/dist/composed/file-preview/embed-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/image-preview.d.ts +2 -1
- package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/shared.d.ts +5 -5
- package/dist/composed/file-preview/shared.d.ts.map +1 -1
- package/dist/composed/file-preview/video-preview.d.ts +2 -1
- package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.d.ts +1 -1
- package/dist/composed/file-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.d.ts +2 -2
- package/dist/composed/filter-bar.d.ts.map +1 -1
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/form-section.js.map +1 -1
- package/dist/composed/global-loading.js.map +1 -1
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/composed/lib/string-utils.js.map +1 -1
- package/dist/composed/loading-skeleton.js.map +1 -1
- package/dist/composed/markdown-viewer.js.map +1 -1
- package/dist/composed/master-detail.d.ts +3 -3
- package/dist/composed/master-detail.d.ts.map +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/member-picker.js.map +1 -1
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/page-header.js.map +1 -1
- package/dist/composed/page-skeletons.js.map +1 -1
- package/dist/composed/priority-indicator.js.map +1 -1
- package/dist/composed/responsive-modal.js +8 -4
- package/dist/composed/responsive-modal.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts +2 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/chat-toolbar.d.ts +17 -17
- package/dist/composed/rich-chat-input/chat-toolbar.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/recording-overlay.d.ts +2 -1
- package/dist/composed/rich-chat-input/recording-overlay.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/reply-banner.d.ts +2 -1
- package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts +4 -3
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +2 -1
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +2 -1
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/composed/simple-tooltip.js.map +1 -1
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/hooks/use-color-mode.js +2 -1
- package/dist/hooks/use-color-mode.js.map +1 -1
- package/dist/hooks/use-mobile.js.map +1 -1
- package/dist/hooks/use-touch-device.js.map +1 -1
- package/dist/hooks/use-viewport-height.js.map +1 -1
- package/dist/motion/index.js.map +1 -1
- package/dist/motion/motion-provider.d.ts +1 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/motion/primitives-index.js.map +1 -1
- package/dist/shell/app-command-palette.js.map +1 -1
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/command-registry.d.ts +1 -1
- package/dist/shell/command-registry.d.ts.map +1 -1
- package/dist/shell/command-registry.js.map +1 -1
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/aspect-ratio.js.map +1 -1
- package/dist/ui/autocomplete.d.ts.map +1 -1
- package/dist/ui/autocomplete.js +8 -0
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.d.ts +1 -1
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-group.d.ts +2 -6
- package/dist/ui/badge-group.d.ts.map +1 -1
- package/dist/ui/badge-indicator.d.ts +2 -6
- package/dist/ui/badge-indicator.d.ts.map +1 -1
- package/dist/ui/badge-indicator.js +19 -18
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +2 -4
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/breadcrumb.d.ts +2 -2
- package/dist/ui/breadcrumb.js.map +1 -1
- package/dist/ui/button-group.js.map +1 -1
- package/dist/ui/button-processing.d.ts +2 -1
- package/dist/ui/button-processing.d.ts.map +1 -1
- package/dist/ui/button-processing.js.map +1 -1
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.js +1 -1
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/charts/_internal/axes.d.ts +2 -1
- package/dist/ui/charts/_internal/axes.d.ts.map +1 -1
- package/dist/ui/charts/_internal/grid-lines.d.ts +2 -1
- package/dist/ui/charts/_internal/grid-lines.d.ts.map +1 -1
- package/dist/ui/charts/_internal/legend.d.ts +2 -1
- package/dist/ui/charts/_internal/legend.d.ts.map +1 -1
- package/dist/ui/charts/_internal/tooltip.d.ts +1 -1
- package/dist/ui/charts/_internal/tooltip.d.ts.map +1 -1
- package/dist/ui/charts/area-chart.js.map +1 -1
- package/dist/ui/charts/bar-chart.js.map +1 -1
- package/dist/ui/charts/gauge-chart.js.map +1 -1
- package/dist/ui/charts/line-chart.js.map +1 -1
- package/dist/ui/charts/pie-chart.js.map +1 -1
- package/dist/ui/charts/radar-chart.js.map +1 -1
- package/dist/ui/charts/sparkline.js +2 -2
- package/dist/ui/charts/sparkline.js.map +1 -1
- package/dist/ui/chat/date-separator.d.ts +2 -1
- package/dist/ui/chat/date-separator.d.ts.map +1 -1
- package/dist/ui/chat/message.d.ts +8 -8
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/typing-indicator.d.ts +2 -1
- package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
- package/dist/ui/chat/unread-separator.d.ts +2 -1
- package/dist/ui/chat/unread-separator.d.ts.map +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/collapsible.js.map +1 -1
- package/dist/ui/color-input.d.ts.map +1 -1
- package/dist/ui/color-input.js +156 -149
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/color-swatch.js.map +1 -1
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +137 -127
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/container.js.map +1 -1
- package/dist/ui/context-menu.d.ts +2 -2
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.d.ts +1 -1
- package/dist/ui/data-table-body.d.ts.map +1 -1
- package/dist/ui/data-table-body.js +1 -1
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-bulk-actions.d.ts +2 -1
- package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
- package/dist/ui/data-table-bulk-actions.js.map +1 -1
- package/dist/ui/data-table-card.d.ts +1 -1
- package/dist/ui/data-table-card.d.ts.map +1 -1
- package/dist/ui/data-table-card.js.map +1 -1
- package/dist/ui/data-table-context.d.ts +1 -1
- package/dist/ui/data-table-context.d.ts.map +1 -1
- package/dist/ui/data-table-context.js.map +1 -1
- package/dist/ui/data-table-header.d.ts +2 -1
- package/dist/ui/data-table-header.d.ts.map +1 -1
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.d.ts +2 -1
- package/dist/ui/data-table-pagination.d.ts.map +1 -1
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/data-table-toolbar.d.ts +1 -1
- package/dist/ui/data-table-toolbar.d.ts.map +1 -1
- package/dist/ui/data-table-toolbar.js.map +1 -1
- package/dist/ui/data-table.d.ts +1 -1
- package/dist/ui/data-table.d.ts.map +1 -1
- package/dist/ui/data-table.js.map +1 -1
- package/dist/ui/devalok-grain.d.ts +2 -1
- package/dist/ui/devalok-grain.d.ts.map +1 -1
- package/dist/ui/devalok-grain.js.map +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dot.js +1 -1
- package/dist/ui/dot.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts +1 -1
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/icon-context.d.ts +1 -1
- package/dist/ui/icon-context.d.ts.map +1 -1
- package/dist/ui/icon-context.js.map +1 -1
- package/dist/ui/icon-group.js.map +1 -1
- package/dist/ui/icon.js.map +1 -1
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/label.js.map +1 -1
- package/dist/ui/lib/bottom-sheet.d.ts +1 -1
- package/dist/ui/lib/bottom-sheet.d.ts.map +1 -1
- package/dist/ui/lib/date-utils.js.map +1 -1
- package/dist/ui/lib/link-context.d.ts +1 -1
- package/dist/ui/lib/link-context.d.ts.map +1 -1
- package/dist/ui/lib/motion.js.map +1 -1
- package/dist/ui/lib/utils.js.map +1 -1
- package/dist/ui/link.js.map +1 -1
- package/dist/ui/menubar.d.ts +1 -1
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.js +14 -9
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/number-input.d.ts.map +1 -1
- package/dist/ui/number-input.js +2 -1
- package/dist/ui/number-input.js.map +1 -1
- package/dist/ui/pagination.js.map +1 -1
- package/dist/ui/progress-ring.js.map +1 -1
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/search-input.js.map +1 -1
- package/dist/ui/segmented-control.js.map +1 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +1 -0
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/separator.js.map +1 -1
- package/dist/ui/sheet.js.map +1 -1
- package/dist/ui/sidebar.js +1 -1
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/skeleton.js.map +1 -1
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/spinner.js.map +1 -1
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stack.js.map +1 -1
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stat-flash.d.ts +2 -1
- package/dist/ui/stat-flash.d.ts.map +1 -1
- package/dist/ui/stat-flash.js +1 -1
- package/dist/ui/stat-flash.js.map +1 -1
- package/dist/ui/stepper.d.ts +1 -1
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +1 -1
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/surface.js.map +1 -1
- package/dist/ui/switch.d.ts +1 -1
- package/dist/ui/switch.js.map +1 -1
- package/dist/ui/table-row-link.js.map +1 -1
- package/dist/ui/table.js.map +1 -1
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/text.js.map +1 -1
- package/dist/ui/textarea.d.ts.map +1 -1
- package/dist/ui/textarea.js +3 -2
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast-registry.js.map +1 -1
- package/dist/ui/toast.d.ts +4 -4
- package/dist/ui/toast.d.ts.map +1 -1
- package/dist/ui/toast.js +5 -3
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toaster.js.map +1 -1
- package/dist/ui/toggle-group.js.map +1 -1
- package/dist/ui/toggle.js.map +1 -1
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/ui/truncated-text.js.map +1 -1
- package/dist/ui/visually-hidden.js.map +1 -1
- package/docs/components/ui/data-table.md +2 -2
- package/llms.txt +1 -1
- package/mcp-manifest.json +3 -3
- package/package.json +21 -21
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-input.js","names":[],"sources":["../../src/ui/color-input.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { HexColorPicker } from 'react-colorful'\n\nimport { durations,springs } from './lib/motion'\nimport { cn } from './lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from './popover'\n\n// ── Color conversion helpers ──\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex)\n if (!m) return null\n const n = parseInt(m[1], 16)\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 }\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('')\n}\n\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } | null {\n const rgb = hexToRgb(hex)\n if (!rgb) return null\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255\n const max = Math.max(r, g, b), min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) }\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max - min)\n let h = 0\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n else if (max === g) h = ((b - r) / d + 2) / 6\n else h = ((r - g) / d + 4) / 6\n return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }\n}\n\nfunction hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100, ln = l / 100\n const a = sn * Math.min(ln, 1 - ln)\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n const c = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * c)\n }\n return rgbToHex(f(0), f(8), f(4))\n}\n\n// ── Named color presets ──\n// Brand spectrum derived from our OKLCH scales (step-9), spanning the wheel —\n// intentional and on-brand, NOT the raw framework palette. Led by red, not indigo.\n\nconst NAMED_PRESETS: { hex: string; label: string }[] = [\n { hex: '#C53637', label: 'Red' },\n { hex: '#BE5A0A', label: 'Orange' },\n { hex: '#DF911A', label: 'Amber' },\n { hex: '#308639', label: 'Green' },\n { hex: '#118659', label: 'Emerald' },\n { hex: '#11846E', label: 'Teal' },\n { hex: '#028A9B', label: 'Cyan' },\n { hex: '#1479B0', label: 'Blue' },\n { hex: '#7D5FAD', label: 'Purple' },\n { hex: '#C22D6D', label: 'Pink' },\n]\n\n// ── Contrast helper ──\n\nfunction isLightColor(hex: string): boolean {\n const rgb = hexToRgb(hex)\n if (!rgb) return false\n // Relative luminance (sRGB)\n const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {\n const s = c / 255\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.4\n}\n\n// ── Format mode type ──\n\ntype ColorFormat = 'hex' | 'rgb' | 'hsl'\n\n// ── Props ──\n\nexport interface ColorInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current color value (hex string, e.g. \"#d33163\") */\n value?: string\n /** Called when the color changes */\n onChange?: (value: string) => void\n /** Preset color swatches. Defaults to 10 named colors. Pass `false` to hide. */\n presets?: { hex: string; label: string }[] | string[] | false\n /** Whether the input is disabled */\n disabled?: boolean\n /** Show the interactive color picker. Default: true. */\n showPicker?: boolean\n /** Default format for the input fields. Default: 'hex'. */\n defaultFormat?: ColorFormat\n /** Popover alignment. Default: 'start'. */\n align?: 'start' | 'center' | 'end'\n /**\n * Trigger style variant.\n * - `default`: Swatch bleeds to left edge + hex text\n * - `inline`: Entire trigger is the selected color with hex text overlaid\n */\n variant?: 'default' | 'inline'\n}\n\n// ── Small format input ──\n\nfunction FormatInput({\n label,\n value,\n onChange,\n onBlur,\n disabled,\n maxLength = 3,\n prefix,\n className,\n id,\n}: {\n label: string\n value: string\n onChange: (v: string) => void\n onBlur?: () => void\n disabled?: boolean\n maxLength?: number\n prefix?: string\n className?: string\n id: string\n}) {\n return (\n <div className={cn('flex flex-col gap-ds-01', className)}>\n <label htmlFor={id} className=\"text-ds-xs font-medium uppercase tracking-wider text-surface-fg-muted\">\n {label}\n </label>\n <div className=\"flex items-center\">\n {prefix && (\n <span className=\"text-ds-sm text-surface-fg-muted\">{prefix}</span>\n )}\n <input\n id={id}\n type=\"text\"\n value={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n maxLength={maxLength}\n className={cn(\n 'h-ds-xs-plus w-full rounded-control-inner border border-surface-border bg-surface-overlay px-ds-02 font-mono text-ds-sm text-surface-fg transition-colors',\n 'focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n />\n </div>\n </div>\n )\n}\n\n// ── Main component ──\n\nconst ColorInput = React.forwardRef<HTMLDivElement, ColorInputProps>(\n ({\n value = '#000000',\n onChange,\n presets,\n disabled = false,\n showPicker = true,\n defaultFormat = 'hex',\n align = 'start',\n variant = 'default',\n className,\n ...props\n }, ref) => {\n const [format, setFormat] = React.useState<ColorFormat>(defaultFormat)\n const [open, setOpen] = React.useState(false)\n const instanceId = React.useId()\n\n // Internal color state — syncs with prop, allows uncontrolled use\n const [internalColor, setInternalColor] = React.useState(value)\n React.useEffect(() => { setInternalColor(value) }, [value])\n\n // Track color when popover opened (for reset) + undo history\n const [openColor, setOpenColor] = React.useState(value)\n const [undoStack, setUndoStack] = React.useState<string[]>([])\n // Track whether current change is from continuous drag (skip undo push)\n const isDragging = React.useRef(false)\n\n const handleOpenChange = (isOpen: boolean) => {\n if (disabled) return\n if (isOpen) {\n setOpenColor(internalColor)\n setUndoStack([])\n }\n setOpen(isOpen)\n }\n\n // Discrete change (preset click, field commit) — pushes to undo\n const handleDiscreteChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Continuous change (picker drag) — updates color but only pushes undo on drag start\n const handleChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n if (!isDragging.current) {\n // First change in a drag sequence — push current color to undo\n isDragging.current = true\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n }\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Called when picker drag ends\n const handlePickerChangeComplete = () => {\n isDragging.current = false\n }\n\n const handleUndo = () => {\n if (undoStack.length === 0) return\n const prev = undoStack[undoStack.length - 1]\n setUndoStack((s) => s.slice(0, -1))\n setInternalColor(prev)\n onChange?.(prev)\n }\n\n const handleReset = () => {\n setInternalColor(openColor)\n onChange?.(openColor)\n setUndoStack([])\n }\n\n // Resolve presets\n const resolvedPresets = presets === false\n ? []\n : presets\n ? presets.map((p) =>\n typeof p === 'string' ? { hex: p, label: p } : p\n )\n : NAMED_PRESETS\n\n // Parsed color values — use internal state\n const rgb = hexToRgb(internalColor)\n const hsl = hexToHsl(internalColor)\n\n // RGB field handlers (clamped 0-255)\n const handleRgbChange = (channel: 'r' | 'g' | 'b', v: string) => {\n if (!rgb) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const clamped = Math.max(0, Math.min(255, num))\n handleDiscreteChange(rgbToHex(\n channel === 'r' ? clamped : rgb.r,\n channel === 'g' ? clamped : rgb.g,\n channel === 'b' ? clamped : rgb.b,\n ))\n }\n\n // HSL field handlers (H: 0-360, S/L: 0-100)\n const handleHslChange = (channel: 'h' | 's' | 'l', v: string) => {\n if (!hsl) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const max = channel === 'h' ? 360 : 100\n const clamped = Math.max(0, Math.min(max, num))\n handleDiscreteChange(hslToHex(\n channel === 'h' ? clamped : hsl.h,\n channel === 's' ? clamped : hsl.s,\n channel === 'l' ? clamped : hsl.l,\n ))\n }\n\n const formats: ColorFormat[] = ['hex', 'rgb', 'hsl']\n\n return (\n <div ref={ref} className={cn('inline-flex flex-col', className)} {...props}>\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n {variant === 'inline' ? (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group flex items-center justify-center rounded-control px-ds-04 py-ds-02 font-mono text-ds-sm font-medium',\n 'focus:outline-hidden focus:ring-2 focus:ring-accent-9 focus:ring-offset-2 focus:ring-offset-surface-base',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n animate={{\n backgroundColor: internalColor,\n color: isLightColor(internalColor) ? 'rgba(0,0,0,0.8)' : 'rgba(255,255,255,0.95)',\n }}\n whileHover={{ y: -1, boxShadow: '0 4px 12px rgba(0,0,0,0.12)' }}\n whileTap={{ scale: 0.97 }}\n transition={springs.smooth}\n aria-label={`Color picker: ${internalColor}`}\n >\n {internalColor.toUpperCase()}\n </motion.button>\n ) : (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group relative flex items-center overflow-hidden rounded-control border border-surface-border-strong',\n 'hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n aria-label={`Color picker: ${internalColor}`}\n >\n {/* Gradient background: color → surface */}\n <motion.span\n className=\"absolute inset-0\"\n animate={{\n background: `linear-gradient(to right, ${internalColor} 0%, ${internalColor} 35%, transparent 70%)`,\n }}\n /* Between durations.moderate02 (0.24) and durations.slow01 (0.4) — gradient lerp feel */\n transition={{ duration: 0.3 }}\n />\n <span className=\"absolute inset-0 bg-surface-overlay/60\" style={{\n maskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n WebkitMaskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n }} />\n {/* Hex value */}\n <span className=\"relative z-10 py-ds-02 pl-6 pr-ds-03 font-mono text-ds-sm text-surface-fg\">\n {internalColor.toUpperCase()}\n </span>\n </motion.button>\n )}\n </PopoverTrigger>\n\n <PopoverContent\n role=\"dialog\"\n aria-label=\"Color picker\"\n align={align}\n sideOffset={8}\n className=\"w-[272px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n >\n <div className=\"flex flex-col\">\n {/* Interactive picker */}\n {showPicker && (\n <div className=\"p-ds-04 pb-ds-03\" onPointerUp={handlePickerChangeComplete} onPointerLeave={handlePickerChangeComplete}>\n <HexColorPicker\n color={internalColor}\n onChange={handleChange}\n className=\"w-full!\"\n style={{ height: 160 }}\n />\n </div>\n )}\n\n {/* Format inputs */}\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n {/* Format switcher */}\n <div className=\"mb-ds-03 flex items-center gap-ds-01\">\n {formats.map((f) => (\n <button\n key={f}\n type=\"button\"\n onClick={() => setFormat(f)}\n className={cn(\n 'relative min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider transition-colors',\n format === f\n ? 'text-accent-11'\n : 'text-surface-fg-muted hover:text-surface-fg',\n )}\n >\n {format === f && (\n <motion.span\n layoutId={`color-input-format-pill-${instanceId}`}\n className=\"absolute inset-0 rounded-control-inner bg-accent-3\"\n transition={springs.snappy}\n />\n )}\n <span className=\"relative z-10\">{f}</span>\n </button>\n ))}\n </div>\n\n {/* Format fields — animated swap */}\n <AnimatePresence mode=\"wait\">\n {format === 'hex' && (\n <motion.div\n key=\"hex\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput\n id={`${instanceId}-hex`}\n label=\"Hex\"\n value={internalColor.replace('#', '').toUpperCase()}\n onChange={(v) => {\n const clean = v.replace(/[^0-9a-fA-F]/g, '').slice(0, 6)\n if (clean.length === 6) handleDiscreteChange(`#${clean}`)\n }}\n onBlur={() => {\n // Revert display to current color if input is incomplete\n const display = internalColor.replace('#', '').toUpperCase()\n if (display.length !== 6) setInternalColor(internalColor)\n }}\n disabled={disabled}\n maxLength={6}\n prefix=\"#\"\n className=\"flex-1\"\n />\n </motion.div>\n )}\n\n {format === 'rgb' && rgb && (\n <motion.div\n key=\"rgb\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-r`} label=\"R\" value={String(rgb.r)} onChange={(v) => handleRgbChange('r', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-g`} label=\"G\" value={String(rgb.g)} onChange={(v) => handleRgbChange('g', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-b`} label=\"B\" value={String(rgb.b)} onChange={(v) => handleRgbChange('b', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n\n {format === 'hsl' && hsl && (\n <motion.div\n key=\"hsl\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-h`} label=\"H\" value={String(hsl.h)} onChange={(v) => handleHslChange('h', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-s`} label=\"S\" value={String(hsl.s)} onChange={(v) => handleHslChange('s', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-l`} label=\"L\" value={String(hsl.l)} onChange={(v) => handleHslChange('l', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Preset swatches */}\n {resolvedPresets.length > 0 && (\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n <div className=\"flex flex-wrap gap-ds-02\">\n {resolvedPresets.map((preset, i) => {\n const isSelected = internalColor.toLowerCase() === preset.hex.toLowerCase()\n return (\n <motion.button\n key={preset.hex}\n type=\"button\"\n disabled={disabled}\n onClick={() => handleDiscreteChange(preset.hex)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: isSelected ? 1.15 : 1 }}\n whileHover={{ scale: isSelected ? 1.15 : 1.1 }}\n whileTap={{ scale: 0.9 }}\n transition={{ ...springs.bouncy, delay: i * 0.02 }}\n className={cn(\n 'h-6 w-6 rounded-control-inner border',\n isSelected\n ? 'border-accent-7 ring-2 ring-accent-9/30'\n : 'border-surface-border hover:border-surface-border-strong',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n style={{ backgroundColor: preset.hex }}\n title={preset.label}\n aria-label={`${preset.label}: ${preset.hex}`}\n />\n )\n })}\n </div>\n </div>\n )}\n\n {/* Reset / Undo footer */}\n {(undoStack.length > 0 || internalColor !== openColor) && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n className=\"flex items-center gap-ds-02 border-t border-surface-border px-ds-04 py-ds-02\"\n >\n {/* Original color preview */}\n <span\n className=\"h-4 w-4 shrink-0 rounded-pill border border-surface-border\"\n style={{ backgroundColor: openColor }}\n title={`Original: ${openColor}`}\n />\n <span className=\"text-ds-xs text-surface-fg-muted\">\n {openColor.toUpperCase()}\n </span>\n <span className=\"flex-1\" />\n {undoStack.length > 0 && (\n <button\n type=\"button\"\n onClick={handleUndo}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-medium text-surface-fg-muted transition-colors hover:text-surface-fg\"\n >\n Undo\n </button>\n )}\n {internalColor !== openColor && (\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-medium text-surface-fg-muted transition-colors hover:text-error-11\"\n >\n Reset\n </button>\n )}\n </motion.div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\nColorInput.displayName = 'ColorInput'\n\nexport { ColorInput }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"color-input.js","names":[],"sources":["../../src/ui/color-input.tsx"],"sourcesContent":["'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\nimport { HexColorPicker } from 'react-colorful'\n\nimport { useFormField } from './form'\nimport { durations,springs } from './lib/motion'\nimport { cn } from './lib/utils'\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from './popover'\n\n// ── Color conversion helpers ──\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex)\n if (!m) return null\n const n = parseInt(m[1], 16)\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 }\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('')\n}\n\nfunction hexToHsl(hex: string): { h: number; s: number; l: number } | null {\n const rgb = hexToRgb(hex)\n if (!rgb) return null\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255\n const max = Math.max(r, g, b), min = Math.min(r, g, b)\n const l = (max + min) / 2\n if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) }\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max - min)\n let h = 0\n if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n else if (max === g) h = ((b - r) / d + 2) / 6\n else h = ((r - g) / d + 4) / 6\n return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }\n}\n\nfunction hslToHex(h: number, s: number, l: number): string {\n const sn = s / 100, ln = l / 100\n const a = sn * Math.min(ln, 1 - ln)\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n const c = ln - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)\n return Math.round(255 * c)\n }\n return rgbToHex(f(0), f(8), f(4))\n}\n\n// ── Named color presets ──\n// Brand spectrum derived from our OKLCH scales (step-9), spanning the wheel —\n// intentional and on-brand, NOT the raw framework palette. Led by red, not indigo.\n\nconst NAMED_PRESETS: { hex: string; label: string }[] = [\n { hex: '#C53637', label: 'Red' },\n { hex: '#BE5A0A', label: 'Orange' },\n { hex: '#DF911A', label: 'Amber' },\n { hex: '#308639', label: 'Green' },\n { hex: '#118659', label: 'Emerald' },\n { hex: '#11846E', label: 'Teal' },\n { hex: '#028A9B', label: 'Cyan' },\n { hex: '#1479B0', label: 'Blue' },\n { hex: '#7D5FAD', label: 'Purple' },\n { hex: '#C22D6D', label: 'Pink' },\n]\n\n// ── Contrast helper ──\n\nfunction isLightColor(hex: string): boolean {\n const rgb = hexToRgb(hex)\n if (!rgb) return false\n // Relative luminance (sRGB)\n const [r, g, b] = [rgb.r, rgb.g, rgb.b].map((c) => {\n const s = c / 255\n return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)\n })\n return 0.2126 * r + 0.7152 * g + 0.0722 * b > 0.4\n}\n\n// ── Format mode type ──\n\ntype ColorFormat = 'hex' | 'rgb' | 'hsl'\n\n// ── Props ──\n\nexport interface ColorInputProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Current color value (hex string, e.g. \"#d33163\") */\n value?: string\n /** Called when the color changes */\n onChange?: (value: string) => void\n /** Preset color swatches. Defaults to 10 named colors. Pass `false` to hide. */\n presets?: { hex: string; label: string }[] | string[] | false\n /** Whether the input is disabled */\n disabled?: boolean\n /** Show the interactive color picker. Default: true. */\n showPicker?: boolean\n /** Default format for the input fields. Default: 'hex'. */\n defaultFormat?: ColorFormat\n /** Popover alignment. Default: 'start'. */\n align?: 'start' | 'center' | 'end'\n /**\n * Trigger style variant.\n * - `default`: Swatch bleeds to left edge + hex text\n * - `inline`: Entire trigger is the selected color with hex text overlaid\n */\n variant?: 'default' | 'inline'\n}\n\n// ── Small format input ──\n\nfunction FormatInput({\n label,\n value,\n onChange,\n onBlur,\n disabled,\n maxLength = 3,\n prefix,\n className,\n id,\n}: {\n label: string\n value: string\n onChange: (v: string) => void\n onBlur?: () => void\n disabled?: boolean\n maxLength?: number\n prefix?: string\n className?: string\n id: string\n}) {\n return (\n <div className={cn('flex flex-col gap-ds-01', className)}>\n <label htmlFor={id} className=\"text-ds-xs font-medium uppercase tracking-wider text-surface-fg-muted\">\n {label}\n </label>\n <div className=\"flex items-center\">\n {prefix && (\n <span className=\"text-ds-sm text-surface-fg-muted\">{prefix}</span>\n )}\n <input\n id={id}\n type=\"text\"\n value={value}\n disabled={disabled}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n maxLength={maxLength}\n className={cn(\n 'h-ds-xs-plus w-full rounded-control-inner border border-surface-border bg-surface-overlay px-ds-02 font-mono text-ds-sm text-surface-fg transition-colors',\n 'focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n />\n </div>\n </div>\n )\n}\n\n// ── Main component ──\n\nconst ColorInput = React.forwardRef<HTMLDivElement, ColorInputProps>(\n ({\n value = '#000000',\n onChange,\n presets,\n disabled = false,\n showPicker = true,\n defaultFormat = 'hex',\n align = 'start',\n variant = 'default',\n className,\n id: externalId,\n ...props\n }, ref) => {\n const [format, setFormat] = React.useState<ColorFormat>(defaultFormat)\n const [open, setOpen] = React.useState(false)\n const instanceId = React.useId()\n const fieldCtx = useFormField()\n // Explicit id wins; otherwise adopt FormField's inputId so <Label htmlFor> resolves\n // onto the (labelable) trigger button. The root is a <div>, which can't be a label target.\n const triggerId = externalId ?? fieldCtx.inputId\n\n // Internal color state — syncs with prop, allows uncontrolled use\n const [internalColor, setInternalColor] = React.useState(value)\n React.useEffect(() => { setInternalColor(value) }, [value])\n\n // Track color when popover opened (for reset) + undo history\n const [openColor, setOpenColor] = React.useState(value)\n const [undoStack, setUndoStack] = React.useState<string[]>([])\n // Track whether current change is from continuous drag (skip undo push)\n const isDragging = React.useRef(false)\n\n const handleOpenChange = (isOpen: boolean) => {\n if (disabled) return\n if (isOpen) {\n setOpenColor(internalColor)\n setUndoStack([])\n }\n setOpen(isOpen)\n }\n\n // Discrete change (preset click, field commit) — pushes to undo\n const handleDiscreteChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Continuous change (picker drag) — updates color but only pushes undo on drag start\n const handleChange = (newValue: string) => {\n if (disabled) return\n const normalized = newValue.startsWith('#') ? newValue : `#${newValue}`\n const hex = normalized.toLowerCase()\n if (!isDragging.current) {\n // First change in a drag sequence — push current color to undo\n isDragging.current = true\n setUndoStack((prev) => {\n if (prev[prev.length - 1] === internalColor) return prev\n return [...prev.slice(-19), internalColor]\n })\n }\n setInternalColor(hex)\n onChange?.(hex)\n }\n\n // Called when picker drag ends\n const handlePickerChangeComplete = () => {\n isDragging.current = false\n }\n\n const handleUndo = () => {\n if (undoStack.length === 0) return\n const prev = undoStack[undoStack.length - 1]\n setUndoStack((s) => s.slice(0, -1))\n setInternalColor(prev)\n onChange?.(prev)\n }\n\n const handleReset = () => {\n setInternalColor(openColor)\n onChange?.(openColor)\n setUndoStack([])\n }\n\n // Resolve presets\n const resolvedPresets = presets === false\n ? []\n : presets\n ? presets.map((p) =>\n typeof p === 'string' ? { hex: p, label: p } : p\n )\n : NAMED_PRESETS\n\n // Parsed color values — use internal state\n const rgb = hexToRgb(internalColor)\n const hsl = hexToHsl(internalColor)\n\n // RGB field handlers (clamped 0-255)\n const handleRgbChange = (channel: 'r' | 'g' | 'b', v: string) => {\n if (!rgb) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const clamped = Math.max(0, Math.min(255, num))\n handleDiscreteChange(rgbToHex(\n channel === 'r' ? clamped : rgb.r,\n channel === 'g' ? clamped : rgb.g,\n channel === 'b' ? clamped : rgb.b,\n ))\n }\n\n // HSL field handlers (H: 0-360, S/L: 0-100)\n const handleHslChange = (channel: 'h' | 's' | 'l', v: string) => {\n if (!hsl) return\n const num = parseInt(v, 10)\n if (isNaN(num)) return\n const max = channel === 'h' ? 360 : 100\n const clamped = Math.max(0, Math.min(max, num))\n handleDiscreteChange(hslToHex(\n channel === 'h' ? clamped : hsl.h,\n channel === 's' ? clamped : hsl.s,\n channel === 'l' ? clamped : hsl.l,\n ))\n }\n\n const formats: ColorFormat[] = ['hex', 'rgb', 'hsl']\n\n return (\n <div ref={ref} className={cn('inline-flex flex-col', className)} {...props}>\n <Popover open={open} onOpenChange={handleOpenChange}>\n <PopoverTrigger asChild>\n {variant === 'inline' ? (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group flex items-center justify-center rounded-control px-ds-04 py-ds-02 font-mono text-ds-sm font-medium',\n 'focus:outline-hidden focus:ring-2 focus:ring-accent-9 focus:ring-offset-2 focus:ring-offset-surface-base',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n animate={{\n backgroundColor: internalColor,\n color: isLightColor(internalColor) ? 'rgba(0,0,0,0.8)' : 'rgba(255,255,255,0.95)',\n }}\n whileHover={{ y: -1, boxShadow: '0 4px 12px rgba(0,0,0,0.12)' }}\n whileTap={{ scale: 0.97 }}\n transition={springs.smooth}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {internalColor.toUpperCase()}\n </motion.button>\n ) : (\n <motion.button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'group relative flex items-center overflow-hidden rounded-control border border-surface-border-strong',\n 'hover:border-accent-7 focus:border-accent-7 focus:outline-hidden focus:ring-1 focus:ring-accent-9',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n whileHover={{ scale: 1.02 }}\n whileTap={{ scale: 0.98 }}\n transition={springs.snappy}\n id={triggerId}\n aria-describedby={fieldCtx.helperTextId}\n aria-invalid={fieldCtx.state === 'error' || undefined}\n // Inside a FormField, let the visible <Label> name the trigger; else describe it.\n aria-label={fieldCtx.inputId ? undefined : `Color picker: ${internalColor}`}\n >\n {/* Gradient background: color → surface */}\n <motion.span\n className=\"absolute inset-0\"\n animate={{\n background: `linear-gradient(to right, ${internalColor} 0%, ${internalColor} 35%, transparent 70%)`,\n }}\n /* Between durations.moderate02 (0.24) and durations.slow01 (0.4) — gradient lerp feel */\n transition={{ duration: 0.3 }}\n />\n <span className=\"absolute inset-0 bg-surface-overlay/60\" style={{\n maskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n WebkitMaskImage: 'linear-gradient(to right, transparent 0%, black 40%)',\n }} />\n {/* Hex value */}\n <span className=\"relative z-10 py-ds-02 pl-6 pr-ds-03 font-mono text-ds-sm text-surface-fg\">\n {internalColor.toUpperCase()}\n </span>\n </motion.button>\n )}\n </PopoverTrigger>\n\n <PopoverContent\n role=\"dialog\"\n aria-label=\"Color picker\"\n align={align}\n sideOffset={8}\n className=\"w-[272px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n >\n <div className=\"flex flex-col\">\n {/* Interactive picker */}\n {showPicker && (\n <div className=\"p-ds-04 pb-ds-03\" onPointerUp={handlePickerChangeComplete} onPointerLeave={handlePickerChangeComplete}>\n <HexColorPicker\n color={internalColor}\n onChange={handleChange}\n className=\"w-full!\"\n style={{ height: 160 }}\n />\n </div>\n )}\n\n {/* Format inputs */}\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n {/* Format switcher */}\n <div className=\"mb-ds-03 flex items-center gap-ds-01\">\n {formats.map((f) => (\n <button\n key={f}\n type=\"button\"\n onClick={() => setFormat(f)}\n className={cn(\n 'relative min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-semibold uppercase tracking-wider transition-colors',\n format === f\n ? 'text-accent-11'\n : 'text-surface-fg-muted hover:text-surface-fg',\n )}\n >\n {format === f && (\n <motion.span\n layoutId={`color-input-format-pill-${instanceId}`}\n className=\"absolute inset-0 rounded-control-inner bg-accent-3\"\n transition={springs.snappy}\n />\n )}\n <span className=\"relative z-10\">{f}</span>\n </button>\n ))}\n </div>\n\n {/* Format fields — animated swap */}\n <AnimatePresence mode=\"wait\">\n {format === 'hex' && (\n <motion.div\n key=\"hex\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput\n id={`${instanceId}-hex`}\n label=\"Hex\"\n value={internalColor.replace('#', '').toUpperCase()}\n onChange={(v) => {\n const clean = v.replace(/[^0-9a-fA-F]/g, '').slice(0, 6)\n if (clean.length === 6) handleDiscreteChange(`#${clean}`)\n }}\n onBlur={() => {\n // Revert display to current color if input is incomplete\n const display = internalColor.replace('#', '').toUpperCase()\n if (display.length !== 6) setInternalColor(internalColor)\n }}\n disabled={disabled}\n maxLength={6}\n prefix=\"#\"\n className=\"flex-1\"\n />\n </motion.div>\n )}\n\n {format === 'rgb' && rgb && (\n <motion.div\n key=\"rgb\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-r`} label=\"R\" value={String(rgb.r)} onChange={(v) => handleRgbChange('r', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-g`} label=\"G\" value={String(rgb.g)} onChange={(v) => handleRgbChange('g', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-b`} label=\"B\" value={String(rgb.b)} onChange={(v) => handleRgbChange('b', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n\n {format === 'hsl' && hsl && (\n <motion.div\n key=\"hsl\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -4 }}\n transition={{ duration: durations.moderate01 }}\n className=\"flex gap-ds-02\"\n >\n <FormatInput id={`${instanceId}-h`} label=\"H\" value={String(hsl.h)} onChange={(v) => handleHslChange('h', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-s`} label=\"S\" value={String(hsl.s)} onChange={(v) => handleHslChange('s', v)} disabled={disabled} className=\"flex-1\" />\n <FormatInput id={`${instanceId}-l`} label=\"L\" value={String(hsl.l)} onChange={(v) => handleHslChange('l', v)} disabled={disabled} className=\"flex-1\" />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n\n {/* Preset swatches */}\n {resolvedPresets.length > 0 && (\n <div className=\"border-t border-surface-border px-ds-04 py-ds-03\">\n <div className=\"flex flex-wrap gap-ds-02\">\n {resolvedPresets.map((preset, i) => {\n const isSelected = internalColor.toLowerCase() === preset.hex.toLowerCase()\n return (\n <motion.button\n key={preset.hex}\n type=\"button\"\n disabled={disabled}\n onClick={() => handleDiscreteChange(preset.hex)}\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: isSelected ? 1.15 : 1 }}\n whileHover={{ scale: isSelected ? 1.15 : 1.1 }}\n whileTap={{ scale: 0.9 }}\n transition={{ ...springs.bouncy, delay: i * 0.02 }}\n className={cn(\n 'h-6 w-6 rounded-control-inner border',\n isSelected\n ? 'border-accent-7 ring-2 ring-accent-9/30'\n : 'border-surface-border hover:border-surface-border-strong',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n style={{ backgroundColor: preset.hex }}\n title={preset.label}\n aria-label={`${preset.label}: ${preset.hex}`}\n />\n )\n })}\n </div>\n </div>\n )}\n\n {/* Reset / Undo footer */}\n {(undoStack.length > 0 || internalColor !== openColor) && (\n <motion.div\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n className=\"flex items-center gap-ds-02 border-t border-surface-border px-ds-04 py-ds-02\"\n >\n {/* Original color preview */}\n <span\n className=\"h-4 w-4 shrink-0 rounded-pill border border-surface-border\"\n style={{ backgroundColor: openColor }}\n title={`Original: ${openColor}`}\n />\n <span className=\"text-ds-xs text-surface-fg-muted\">\n {openColor.toUpperCase()}\n </span>\n <span className=\"flex-1\" />\n {undoStack.length > 0 && (\n <button\n type=\"button\"\n onClick={handleUndo}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-medium text-surface-fg-muted transition-colors hover:text-surface-fg\"\n >\n Undo\n </button>\n )}\n {internalColor !== openColor && (\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"min-h-6 rounded-control-inner px-ds-02 py-px text-ds-xs font-medium text-surface-fg-muted transition-colors hover:text-error-11\"\n >\n Reset\n </button>\n )}\n </motion.div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n )\n },\n)\nColorInput.displayName = 'ColorInput'\n\nexport { ColorInput }\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-swatch.js","names":[],"sources":["../../src/ui/color-swatch.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\nconst sizeMap = {\n sm: 'h-3 w-3',\n md: 'h-4 w-4',\n lg: 'h-6 w-6',\n} as const\n\nconst shapeMap = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control-inner',\n} as const\n\n/**\n * A tiny color swatch for displaying dynamic runtime colors (e.g. brand colors from a database).\n *\n * @example\n * <ColorSwatch color=\"#FF5733\" />\n * <ColorSwatch color={org.brandColor} size=\"lg\" ring />\n * <ColorSwatch color=\"rgba(0,0,0,0.5)\" checkerboard copyable />\n */\nexport interface ColorSwatchProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Any valid CSS color string (hex, rgb, oklch, etc.) */\n color: string\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'circle' */\n shape?: 'circle' | 'square' | 'rounded'\n /** Show subtle ring border — useful for light colors that blend into the background */\n ring?: boolean\n /** Render as a button that copies the color string to clipboard on click */\n copyable?: boolean\n /** Show a checkerboard pattern behind the color — useful for transparent colors */\n checkerboard?: boolean\n}\n\nconst ColorSwatch = React.forwardRef<HTMLSpanElement, ColorSwatchProps>(\n ({ color, size = 'md', shape = 'circle', ring = false, copyable = false, checkerboard = false, className, style, ...props }, ref) => {\n const [copied, setCopied] = React.useState(false)\n const timerRef = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n React.useEffect(() => () => clearTimeout(timerRef.current), [])\n\n const sharedClasses = cn(\n 'inline-block shrink-0 relative',\n sizeMap[size],\n shapeMap[shape],\n ring && 'shadow-ring-sm',\n copyable && 'cursor-pointer',\n className,\n )\n\n const checkerboardStyle: React.CSSProperties = checkerboard\n ? {\n backgroundImage: `repeating-conic-gradient(var(--color-neutral-5) 0% 25%, transparent 0% 50%)`,\n backgroundSize: '8px 8px',\n }\n : {}\n\n const colorOverlayStyle: React.CSSProperties = {\n backgroundColor: color,\n ...style,\n }\n\n function handleCopy() {\n navigator.clipboard.writeText(color).then(() => {\n setCopied(true)\n timerRef.current = setTimeout(() => setCopied(false), 1500)\n })\n }\n\n const inner = checkerboard ? (\n <>\n <span\n className={cn('absolute inset-0', shapeMap[shape])}\n style={checkerboardStyle}\n aria-hidden=\"true\"\n />\n <span\n className={cn('absolute inset-0', shapeMap[shape])}\n style={colorOverlayStyle}\n />\n </>\n ) : null\n\n if (copyable) {\n return (\n <button\n type=\"button\"\n ref={ref as React.Ref<HTMLButtonElement>}\n className={sharedClasses}\n style={checkerboard ? {} : colorOverlayStyle}\n onClick={handleCopy}\n aria-label={`Copy color ${color}`}\n {...(props as React.ButtonHTMLAttributes<HTMLButtonElement>)}\n >\n {inner}\n {copied && (\n <span\n role=\"status\"\n className=\"absolute -top-7 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-control-inner bg-surface-overlay px-1.5 py-0.5 text-[10px] font-sans text-surface-fg shadow-floating\"\n >\n Copied!\n </span>\n )}\n </button>\n )\n }\n\n return (\n <span\n ref={ref}\n className={sharedClasses}\n style={checkerboard ? {} : colorOverlayStyle}\n role=\"presentation\"\n {...props}\n >\n {inner}\n </span>\n )\n },\n)\nColorSwatch.displayName = 'ColorSwatch'\n\nexport { ColorSwatch }\n"],"mappings":";;;;;AAMA,IAAM,IAAU;CACd,IAAI;CACJ,IAAI;CACJ,IAAI;
|
|
1
|
+
{"version":3,"file":"color-swatch.js","names":[],"sources":["../../src/ui/color-swatch.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\n\nimport { cn } from './lib/utils'\n\nconst sizeMap = {\n sm: 'h-3 w-3',\n md: 'h-4 w-4',\n lg: 'h-6 w-6',\n} as const\n\nconst shapeMap = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control-inner',\n} as const\n\n/**\n * A tiny color swatch for displaying dynamic runtime colors (e.g. brand colors from a database).\n *\n * @example\n * <ColorSwatch color=\"#FF5733\" />\n * <ColorSwatch color={org.brandColor} size=\"lg\" ring />\n * <ColorSwatch color=\"rgba(0,0,0,0.5)\" checkerboard copyable />\n */\nexport interface ColorSwatchProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Any valid CSS color string (hex, rgb, oklch, etc.) */\n color: string\n /** @default 'md' */\n size?: 'sm' | 'md' | 'lg'\n /** @default 'circle' */\n shape?: 'circle' | 'square' | 'rounded'\n /** Show subtle ring border — useful for light colors that blend into the background */\n ring?: boolean\n /** Render as a button that copies the color string to clipboard on click */\n copyable?: boolean\n /** Show a checkerboard pattern behind the color — useful for transparent colors */\n checkerboard?: boolean\n}\n\nconst ColorSwatch = React.forwardRef<HTMLSpanElement, ColorSwatchProps>(\n ({ color, size = 'md', shape = 'circle', ring = false, copyable = false, checkerboard = false, className, style, ...props }, ref) => {\n const [copied, setCopied] = React.useState(false)\n const timerRef = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined)\n React.useEffect(() => () => clearTimeout(timerRef.current), [])\n\n const sharedClasses = cn(\n 'inline-block shrink-0 relative',\n sizeMap[size],\n shapeMap[shape],\n ring && 'shadow-ring-sm',\n copyable && 'cursor-pointer',\n className,\n )\n\n const checkerboardStyle: React.CSSProperties = checkerboard\n ? {\n backgroundImage: `repeating-conic-gradient(var(--color-neutral-5) 0% 25%, transparent 0% 50%)`,\n backgroundSize: '8px 8px',\n }\n : {}\n\n const colorOverlayStyle: React.CSSProperties = {\n backgroundColor: color,\n ...style,\n }\n\n function handleCopy() {\n navigator.clipboard.writeText(color).then(() => {\n setCopied(true)\n timerRef.current = setTimeout(() => setCopied(false), 1500)\n })\n }\n\n const inner = checkerboard ? (\n <>\n <span\n className={cn('absolute inset-0', shapeMap[shape])}\n style={checkerboardStyle}\n aria-hidden=\"true\"\n />\n <span\n className={cn('absolute inset-0', shapeMap[shape])}\n style={colorOverlayStyle}\n />\n </>\n ) : null\n\n if (copyable) {\n return (\n <button\n type=\"button\"\n ref={ref as React.Ref<HTMLButtonElement>}\n className={sharedClasses}\n style={checkerboard ? {} : colorOverlayStyle}\n onClick={handleCopy}\n aria-label={`Copy color ${color}`}\n {...(props as React.ButtonHTMLAttributes<HTMLButtonElement>)}\n >\n {inner}\n {copied && (\n <span\n role=\"status\"\n className=\"absolute -top-7 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-control-inner bg-surface-overlay px-1.5 py-0.5 text-[10px] font-sans text-surface-fg shadow-floating\"\n >\n Copied!\n </span>\n )}\n </button>\n )\n }\n\n return (\n <span\n ref={ref}\n className={sharedClasses}\n style={checkerboard ? {} : colorOverlayStyle}\n role=\"presentation\"\n {...props}\n >\n {inner}\n </span>\n )\n },\n)\nColorSwatch.displayName = 'ColorSwatch'\n\nexport { ColorSwatch }\n"],"mappings":";;;;;AAMA,IAAM,IAAU;CACd,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,IAAW;CACf,QAAQ;CACR,QAAQ;CACR,SAAS;AACX,GAyBM,IAAc,EAAM,YACvB,EAAE,UAAO,UAAO,MAAM,WAAQ,UAAU,UAAO,IAAO,cAAW,IAAO,kBAAe,IAAO,cAAW,UAAO,GAAG,KAAS,MAAQ;CACnI,IAAM,CAAC,GAAQ,KAAa,EAAM,SAAS,EAAK,GAC1C,IAAW,EAAM,OAAkD,KAAA,CAAS;CAClF,EAAM,sBAAsB,aAAa,EAAS,OAAO,GAAG,CAAC,CAAC;CAE9D,IAAM,IAAgB,EACpB,kCACA,EAAQ,IACR,EAAS,IACT,KAAQ,kBACR,KAAY,kBACZ,CACF,GAEM,IAAyC,IAC3C;EACE,iBAAiB;EACjB,gBAAgB;CAClB,IACA,CAAC,GAEC,IAAyC;EAC7C,iBAAiB;EACjB,GAAG;CACL;CAEA,SAAS,IAAa;EACpB,UAAU,UAAU,UAAU,CAAK,CAAC,CAAC,WAAW;GAE9C,AADA,EAAU,EAAI,GACd,EAAS,UAAU,iBAAiB,EAAU,EAAK,GAAG,IAAI;EAC5D,CAAC;CACH;CAEA,IAAM,IAAQ,IACZ,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,QAAD;EACE,WAAW,EAAG,oBAAoB,EAAS,EAAM;EACjD,OAAO;EACP,eAAY;CACb,CAAA,GACD,kBAAC,QAAD;EACE,WAAW,EAAG,oBAAoB,EAAS,EAAM;EACjD,OAAO;CACR,CAAA,CACD,EAAA,CAAA,IACA;CA0BJ,OAxBI,IAEA,kBAAC,UAAD;EACE,MAAK;EACA;EACL,WAAW;EACX,OAAO,IAAe,CAAC,IAAI;EAC3B,SAAS;EACT,cAAY,cAAc;EAC1B,GAAK;YAPP,CASG,GACA,KACC,kBAAC,QAAD;GACE,MAAK;GACL,WAAU;aACX;EAEK,CAAA,CAEF;MAKV,kBAAC,QAAD;EACO;EACL,WAAW;EACX,OAAO,IAAe,CAAC,IAAI;EAC3B,MAAK;EACL,GAAI;YAEH;CACG,CAAA;AAEV,CACF;AACA,EAAY,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAYjD,eAAO,MAAM,uBAAuB;;8EAmBnC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AA0B5F;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,UAAU,iBAAkB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IACxF,+CAA+C;IAC/C,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oGAAoG;IACpG,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAA;IAC7E,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,iFAAiF;IACjF,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,8GAA8G;IAC9G,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAED,UAAU,qBAAsB,SAAQ,iBAAiB;IACvD,QAAQ,EAAE,IAAI,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACzC;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAQvE,QAAA,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/ui/combobox.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAYjD,eAAO,MAAM,uBAAuB;;8EAmBnC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AA0B5F;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,UAAU,iBAAkB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IACxF,+CAA+C;IAC/C,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oGAAoG;IACpG,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAA;IAC7E,4FAA4F;IAC5F,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,iFAAiF;IACjF,IAAI,CAAC,EAAE,YAAY,CAAA;IACnB,8GAA8G;IAC9G,KAAK,CAAC,EAAE,UAAU,CAAA;CACnB;AAED,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAED,UAAU,qBAAsB,SAAQ,iBAAiB;IACvD,QAAQ,EAAE,IAAI,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACzC;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,qBAAqB,CAAA;AAQvE,QAAA,MAAM,QAAQ,yFAyZb,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
package/dist/ui/combobox.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Content2$6 as e, Portal$3 as t, Root2$8 as n, Trigger$8 as r } from "../_chunks/primitives.js";
|
|
3
3
|
import { IconProvider as ee } from "./icon-context.js";
|
|
4
|
-
import { springs as
|
|
5
|
-
import { cva as
|
|
6
|
-
import { cn as
|
|
7
|
-
import { Icon as
|
|
8
|
-
import { useFormField as
|
|
9
|
-
import { normalizeIcon as
|
|
4
|
+
import { springs as i, tweens as a } from "./lib/motion.js";
|
|
5
|
+
import { cva as o } from "../_chunks/vendor-utils.js";
|
|
6
|
+
import { cn as s } from "./lib/utils.js";
|
|
7
|
+
import { Icon as c } from "./icon.js";
|
|
8
|
+
import { useFormField as te } from "./form.js";
|
|
9
|
+
import { normalizeIcon as ne } from "../_chunks/normalize-icon.js";
|
|
10
10
|
import { resolveFieldState as re } from "../_chunks/field-state.js";
|
|
11
11
|
import * as l from "react";
|
|
12
|
-
import { Fragment as
|
|
13
|
-
import { IconCheck as
|
|
14
|
-
import { motion as
|
|
12
|
+
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
13
|
+
import { IconCheck as p, IconChevronDown as m, IconSearch as ie, IconX as ae } from "@tabler/icons-react";
|
|
14
|
+
import { motion as oe } from "framer-motion";
|
|
15
15
|
//#region src/ui/combobox.tsx
|
|
16
|
-
var
|
|
16
|
+
var se = {
|
|
17
17
|
error: "border-error-7",
|
|
18
18
|
warning: "border-warning-7",
|
|
19
19
|
success: "border-success-7"
|
|
20
|
-
},
|
|
20
|
+
}, h = o([
|
|
21
21
|
"flex w-full items-center justify-between whitespace-nowrap rounded-control",
|
|
22
22
|
"border border-surface-border-strong bg-surface-raised-hover",
|
|
23
23
|
"transition-colors duration-fast-01 ease-productive-standard",
|
|
@@ -31,113 +31,122 @@ var _ = {
|
|
|
31
31
|
lg: "h-ds-lg text-ds-md px-ds-05"
|
|
32
32
|
} },
|
|
33
33
|
defaultVariants: { size: "md" }
|
|
34
|
-
}),
|
|
34
|
+
}), g = {
|
|
35
35
|
xs: "xs",
|
|
36
36
|
sm: "sm",
|
|
37
37
|
md: "sm",
|
|
38
38
|
lg: "md"
|
|
39
|
-
},
|
|
39
|
+
}, _ = {
|
|
40
40
|
xs: "px-ds-02 py-0 text-ds-xs",
|
|
41
41
|
sm: "px-ds-02 py-0 text-ds-xs",
|
|
42
42
|
md: "px-ds-03 py-[1px] text-ds-sm",
|
|
43
43
|
lg: "px-ds-03 py-[2px] text-ds-sm"
|
|
44
|
-
},
|
|
44
|
+
}, v = {
|
|
45
45
|
xs: "text-ds-xs",
|
|
46
46
|
sm: "text-ds-xs",
|
|
47
47
|
md: "text-ds-sm",
|
|
48
48
|
lg: "text-ds-sm"
|
|
49
|
-
},
|
|
50
|
-
let
|
|
51
|
-
|
|
49
|
+
}, y = 2, b = 36, x = l.forwardRef(({ options: o, value: x, onValueChange: S, placeholder: C = "Select...", searchPlaceholder: w = "Search...", emptyMessage: T = "No results found", multiple: E = !1, disabled: D = !1, className: ce, triggerClassName: le, maxVisible: O = 6, renderOption: k, accessibleLabel: A, id: j, size: M = "md", state: N, ...P }, F) => {
|
|
50
|
+
let I = M ?? "md", [L, R] = l.useState(!1), [z, B] = l.useState(""), [V, H] = l.useState(-1), U = l.useRef(null), W = l.useRef(null), G = l.useId(), K = l.useId(), q = l.useMemo(() => x == null ? [] : Array.isArray(x) ? x : [x], [x]), J = l.useMemo(() => z ? o.filter((e) => e.label.toLowerCase().includes(z.toLowerCase())) : o, [o, z]), ue = l.useCallback((e) => q.includes(e), [q]), Y = l.useCallback((e) => {
|
|
51
|
+
E ? S(q.includes(e) ? q.filter((t) => t !== e) : [...q, e]) : (S(e), R(!1));
|
|
52
52
|
}, [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
E,
|
|
54
|
+
q,
|
|
55
|
+
S
|
|
56
56
|
]), de = l.useCallback((e, t) => {
|
|
57
|
-
e.stopPropagation(), e.preventDefault(),
|
|
58
|
-
}, [
|
|
59
|
-
|
|
60
|
-
}, [
|
|
57
|
+
e.stopPropagation(), e.preventDefault(), S(q.filter((e) => e !== t));
|
|
58
|
+
}, [q, S]), fe = l.useCallback((e) => {
|
|
59
|
+
D || (R(e), e || (B(""), H(-1)));
|
|
60
|
+
}, [D]);
|
|
61
61
|
l.useEffect(() => {
|
|
62
|
-
if (
|
|
62
|
+
if (L) {
|
|
63
63
|
let e = setTimeout(() => {
|
|
64
|
-
|
|
64
|
+
U.current?.focus();
|
|
65
65
|
}, 0);
|
|
66
66
|
return () => clearTimeout(e);
|
|
67
67
|
}
|
|
68
|
-
}, [
|
|
69
|
-
let
|
|
70
|
-
let n =
|
|
68
|
+
}, [L]);
|
|
69
|
+
let X = l.useCallback((e, t) => {
|
|
70
|
+
let n = J.length;
|
|
71
71
|
if (n === 0) return -1;
|
|
72
72
|
let r = e + t;
|
|
73
73
|
for (; r >= 0 && r < n;) {
|
|
74
|
-
if (!
|
|
74
|
+
if (!J[r].disabled) return r;
|
|
75
75
|
r += t;
|
|
76
76
|
}
|
|
77
77
|
return e;
|
|
78
|
-
}, [
|
|
78
|
+
}, [J]), pe = l.useCallback((e) => {
|
|
79
79
|
switch (e.key) {
|
|
80
|
-
case "ArrowDown":
|
|
81
|
-
e.preventDefault()
|
|
80
|
+
case "ArrowDown": {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
let t = X(V, 1);
|
|
83
|
+
H(t);
|
|
82
84
|
break;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
}
|
|
86
|
+
case "ArrowUp": {
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
let t = X(V, -1);
|
|
89
|
+
H(t);
|
|
85
90
|
break;
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
}
|
|
92
|
+
case "Home": {
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
let t = J.findIndex((e) => !e.disabled);
|
|
95
|
+
H(t);
|
|
88
96
|
break;
|
|
97
|
+
}
|
|
89
98
|
case "End": {
|
|
90
99
|
e.preventDefault();
|
|
91
100
|
let t = -1;
|
|
92
|
-
for (let e =
|
|
101
|
+
for (let e = J.length - 1; e >= 0; e--) if (!J[e].disabled) {
|
|
93
102
|
t = e;
|
|
94
103
|
break;
|
|
95
104
|
}
|
|
96
|
-
|
|
105
|
+
H(t);
|
|
97
106
|
break;
|
|
98
107
|
}
|
|
99
108
|
case "Enter":
|
|
100
|
-
e.preventDefault(),
|
|
109
|
+
e.preventDefault(), V >= 0 && V < J.length && !J[V].disabled && Y(J[V].value);
|
|
101
110
|
break;
|
|
102
111
|
case "Escape":
|
|
103
|
-
e.preventDefault(),
|
|
112
|
+
e.preventDefault(), R(!1), B(""), H(-1);
|
|
104
113
|
break;
|
|
105
114
|
}
|
|
106
115
|
}, [
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
V,
|
|
117
|
+
J,
|
|
118
|
+
X,
|
|
119
|
+
Y
|
|
111
120
|
]);
|
|
112
121
|
l.useEffect(() => {
|
|
113
|
-
if (
|
|
114
|
-
let e =
|
|
122
|
+
if (V >= 0 && W.current) {
|
|
123
|
+
let e = W.current.children[V];
|
|
115
124
|
e && e.scrollIntoView?.({ block: "nearest" });
|
|
116
125
|
}
|
|
117
|
-
}, [
|
|
118
|
-
let me = l.useCallback(() =>
|
|
119
|
-
if (
|
|
120
|
-
let e =
|
|
121
|
-
return /* @__PURE__ */
|
|
126
|
+
}, [V]);
|
|
127
|
+
let me = l.useCallback(() => q.length === 0 ? null : o.find((e) => e.value === q[0])?.label ?? null, [q, o]), Z = g[I], he = _[I], ge = v[I], _e = () => {
|
|
128
|
+
if (E && q.length > 0) {
|
|
129
|
+
let e = q.slice(0, y), t = q.length - y;
|
|
130
|
+
return /* @__PURE__ */ f("span", {
|
|
122
131
|
className: "flex flex-1 flex-wrap items-center gap-ds-02 overflow-hidden",
|
|
123
132
|
children: [e.map((e) => {
|
|
124
|
-
let t =
|
|
125
|
-
return t ? /* @__PURE__ */
|
|
126
|
-
className:
|
|
127
|
-
children: [t.label, /* @__PURE__ */
|
|
133
|
+
let t = o.find((t) => t.value === e);
|
|
134
|
+
return t ? /* @__PURE__ */ f("span", {
|
|
135
|
+
className: s("inline-flex items-center gap-ds-01 rounded-control-inner bg-accent-2", he),
|
|
136
|
+
children: [t.label, /* @__PURE__ */ d("button", {
|
|
128
137
|
type: "button",
|
|
129
138
|
className: "inline-flex items-center justify-center rounded-pill outline-hidden hover:bg-surface-raised-hover transition-colors duration-fast-01 ease-productive-standard",
|
|
130
139
|
onClick: (t) => de(t, e),
|
|
131
140
|
"aria-label": `Remove ${t.label}`,
|
|
132
141
|
tabIndex: -1,
|
|
133
|
-
children: /* @__PURE__ */
|
|
134
|
-
icon:
|
|
135
|
-
size:
|
|
142
|
+
children: /* @__PURE__ */ d(c, {
|
|
143
|
+
icon: ae,
|
|
144
|
+
size: Z
|
|
136
145
|
})
|
|
137
146
|
})]
|
|
138
147
|
}, e) : null;
|
|
139
|
-
}), t > 0 && /* @__PURE__ */
|
|
140
|
-
className:
|
|
148
|
+
}), t > 0 && /* @__PURE__ */ f("span", {
|
|
149
|
+
className: s("text-surface-fg-muted", ge),
|
|
141
150
|
children: [
|
|
142
151
|
"+",
|
|
143
152
|
t,
|
|
@@ -146,54 +155,55 @@ var _ = {
|
|
|
146
155
|
})]
|
|
147
156
|
});
|
|
148
157
|
}
|
|
149
|
-
if (!
|
|
158
|
+
if (!E && q.length === 1) {
|
|
150
159
|
let e = me();
|
|
151
|
-
if (e) return /* @__PURE__ */
|
|
160
|
+
if (e) return /* @__PURE__ */ d("span", {
|
|
152
161
|
className: "min-w-0 flex-1 truncate text-left",
|
|
153
162
|
children: e
|
|
154
163
|
});
|
|
155
164
|
}
|
|
156
|
-
return /* @__PURE__ */
|
|
165
|
+
return /* @__PURE__ */ d("span", {
|
|
157
166
|
className: "min-w-0 flex-1 truncate text-left text-surface-fg-subtle",
|
|
158
|
-
children:
|
|
167
|
+
children: C
|
|
159
168
|
});
|
|
160
|
-
}, Q =
|
|
161
|
-
return /* @__PURE__ */
|
|
162
|
-
open:
|
|
169
|
+
}, Q = te(), $ = re(N, Q.state), ve = $ === "error", ye = Q.helperTextId, be = Q.required;
|
|
170
|
+
return /* @__PURE__ */ d(n, {
|
|
171
|
+
open: L,
|
|
163
172
|
onOpenChange: fe,
|
|
164
|
-
children: /* @__PURE__ */
|
|
165
|
-
className:
|
|
166
|
-
...
|
|
167
|
-
children: [/* @__PURE__ */
|
|
173
|
+
children: /* @__PURE__ */ f("div", {
|
|
174
|
+
className: s("relative", ce),
|
|
175
|
+
...P,
|
|
176
|
+
children: [/* @__PURE__ */ d(r, {
|
|
168
177
|
asChild: !0,
|
|
169
|
-
disabled:
|
|
170
|
-
children: /* @__PURE__ */
|
|
171
|
-
ref:
|
|
178
|
+
disabled: D,
|
|
179
|
+
children: /* @__PURE__ */ f("button", {
|
|
180
|
+
ref: F,
|
|
172
181
|
type: "button",
|
|
173
182
|
role: "combobox",
|
|
174
|
-
|
|
175
|
-
"aria-
|
|
183
|
+
id: j ?? Q.inputId,
|
|
184
|
+
"aria-expanded": L,
|
|
185
|
+
"aria-controls": K,
|
|
176
186
|
"aria-haspopup": "listbox",
|
|
177
|
-
"aria-label": A ??
|
|
178
|
-
"aria-invalid":
|
|
179
|
-
"aria-describedby":
|
|
180
|
-
"aria-required":
|
|
181
|
-
disabled:
|
|
182
|
-
className:
|
|
183
|
-
children: [
|
|
184
|
-
icon:
|
|
185
|
-
size:
|
|
186
|
-
className:
|
|
187
|
+
"aria-label": A ?? (Q.inputId ? void 0 : C),
|
|
188
|
+
"aria-invalid": ve || void 0,
|
|
189
|
+
"aria-describedby": ye,
|
|
190
|
+
"aria-required": be || void 0,
|
|
191
|
+
disabled: D,
|
|
192
|
+
className: s(h({ size: I }), L && "border-accent-7", $ && se[$], le),
|
|
193
|
+
children: [_e(), /* @__PURE__ */ d(c, {
|
|
194
|
+
icon: m,
|
|
195
|
+
size: Z,
|
|
196
|
+
className: s("ml-ds-02 shrink-0 opacity-50 transition-transform duration-fast-01 ease-productive-standard", L && "rotate-180")
|
|
187
197
|
})]
|
|
188
198
|
})
|
|
189
|
-
}), /* @__PURE__ */
|
|
199
|
+
}), /* @__PURE__ */ d(t, { children: /* @__PURE__ */ d(e, {
|
|
190
200
|
asChild: !0,
|
|
191
201
|
sideOffset: 4,
|
|
192
202
|
align: "start",
|
|
193
203
|
onOpenAutoFocus: (e) => {
|
|
194
|
-
e.preventDefault(),
|
|
204
|
+
e.preventDefault(), U.current?.focus();
|
|
195
205
|
},
|
|
196
|
-
children: /* @__PURE__ */
|
|
206
|
+
children: /* @__PURE__ */ f(oe.div, {
|
|
197
207
|
initial: {
|
|
198
208
|
opacity: 0,
|
|
199
209
|
scale: .95
|
|
@@ -203,75 +213,75 @@ var _ = {
|
|
|
203
213
|
scale: 1
|
|
204
214
|
},
|
|
205
215
|
transition: {
|
|
206
|
-
...
|
|
207
|
-
opacity:
|
|
216
|
+
...i.snappy,
|
|
217
|
+
opacity: a.fade
|
|
208
218
|
},
|
|
209
|
-
className:
|
|
210
|
-
children: [/* @__PURE__ */
|
|
219
|
+
className: s("z-popover w-[var(--radix-popover-trigger-width)] overflow-hidden rounded-overlay bg-surface-overlay shadow-floating"),
|
|
220
|
+
children: [/* @__PURE__ */ f("div", {
|
|
211
221
|
className: "flex items-center gap-ds-02 border-b border-surface-border px-ds-04",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
213
|
-
icon:
|
|
222
|
+
children: [/* @__PURE__ */ d(c, {
|
|
223
|
+
icon: ie,
|
|
214
224
|
size: "sm",
|
|
215
225
|
className: "shrink-0 text-surface-fg-subtle"
|
|
216
|
-
}), /* @__PURE__ */
|
|
217
|
-
ref:
|
|
226
|
+
}), /* @__PURE__ */ d("input", {
|
|
227
|
+
ref: U,
|
|
218
228
|
type: "text",
|
|
219
229
|
className: "flex-1 bg-transparent py-ds-03 text-ds-md outline-hidden placeholder:text-surface-fg-subtle",
|
|
220
|
-
placeholder:
|
|
221
|
-
value:
|
|
230
|
+
placeholder: w,
|
|
231
|
+
value: z,
|
|
222
232
|
onChange: (e) => {
|
|
223
|
-
|
|
233
|
+
B(e.target.value), H(-1);
|
|
224
234
|
},
|
|
225
235
|
onKeyDown: pe,
|
|
226
236
|
"aria-autocomplete": "list",
|
|
227
|
-
"aria-controls":
|
|
228
|
-
"aria-activedescendant":
|
|
237
|
+
"aria-controls": K,
|
|
238
|
+
"aria-activedescendant": V >= 0 ? `${G}-option-${V}` : void 0,
|
|
229
239
|
"aria-label": "Search options"
|
|
230
240
|
})]
|
|
231
|
-
}),
|
|
241
|
+
}), J.length === 0 ? /* @__PURE__ */ d("div", {
|
|
232
242
|
className: "px-ds-04 py-ds-05 text-center text-ds-md text-surface-fg-subtle",
|
|
233
|
-
children:
|
|
234
|
-
}) : /* @__PURE__ */
|
|
235
|
-
ref:
|
|
236
|
-
id:
|
|
243
|
+
children: T
|
|
244
|
+
}) : /* @__PURE__ */ d("ul", {
|
|
245
|
+
ref: W,
|
|
246
|
+
id: K,
|
|
237
247
|
role: "listbox",
|
|
238
|
-
"aria-multiselectable":
|
|
248
|
+
"aria-multiselectable": E || void 0,
|
|
239
249
|
className: "overflow-auto p-ds-02",
|
|
240
|
-
style: { maxHeight: `${O *
|
|
241
|
-
children:
|
|
250
|
+
style: { maxHeight: `${O * b}px` },
|
|
251
|
+
children: J.map((e, t) => {
|
|
242
252
|
let n = ue(e.value);
|
|
243
|
-
return /* @__PURE__ */
|
|
244
|
-
id: `${
|
|
253
|
+
return /* @__PURE__ */ f("li", {
|
|
254
|
+
id: `${G}-option-${t}`,
|
|
245
255
|
role: "option",
|
|
246
256
|
"aria-selected": n,
|
|
247
257
|
"aria-disabled": e.disabled || void 0,
|
|
248
|
-
className:
|
|
258
|
+
className: s("relative flex cursor-pointer select-none items-center gap-ds-03 rounded-control px-ds-04 py-ds-03 text-ds-md outline-hidden", "transition-colors duration-fast-01 ease-productive-standard", V === t && "bg-accent-2", n && "text-accent-11", e.disabled && "pointer-events-none opacity-action-disabled"),
|
|
249
259
|
onClick: () => {
|
|
250
|
-
e.disabled ||
|
|
260
|
+
e.disabled || Y(e.value);
|
|
251
261
|
},
|
|
252
262
|
onKeyDown: (t) => {
|
|
253
|
-
!e.disabled && (t.key === "Enter" || t.key === " ") && (t.preventDefault(),
|
|
263
|
+
!e.disabled && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), Y(e.value));
|
|
254
264
|
},
|
|
255
265
|
onMouseEnter: () => {
|
|
256
|
-
e.disabled ||
|
|
266
|
+
e.disabled || H(t);
|
|
257
267
|
},
|
|
258
268
|
children: [
|
|
259
|
-
e.icon && /* @__PURE__ */
|
|
269
|
+
e.icon && /* @__PURE__ */ d("span", {
|
|
260
270
|
className: "flex h-ico-sm w-ico-sm items-center justify-center shrink-0",
|
|
261
|
-
children: /* @__PURE__ */
|
|
262
|
-
size:
|
|
263
|
-
children:
|
|
271
|
+
children: /* @__PURE__ */ d(ee, {
|
|
272
|
+
size: Z,
|
|
273
|
+
children: ne(e.icon)
|
|
264
274
|
})
|
|
265
275
|
}),
|
|
266
|
-
/* @__PURE__ */
|
|
276
|
+
/* @__PURE__ */ d("span", {
|
|
267
277
|
className: "flex flex-1 flex-col",
|
|
268
|
-
children: k ? k(e, n) : /* @__PURE__ */
|
|
278
|
+
children: k ? k(e, n) : /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("span", { children: e.label }), e.description && /* @__PURE__ */ d("span", {
|
|
269
279
|
className: "text-ds-sm text-surface-fg-muted",
|
|
270
280
|
children: e.description
|
|
271
281
|
})] })
|
|
272
282
|
}),
|
|
273
|
-
n && /* @__PURE__ */
|
|
274
|
-
icon:
|
|
283
|
+
n && /* @__PURE__ */ d(c, {
|
|
284
|
+
icon: p,
|
|
275
285
|
size: "sm",
|
|
276
286
|
className: "shrink-0"
|
|
277
287
|
})
|
|
@@ -284,6 +294,6 @@ var _ = {
|
|
|
284
294
|
})
|
|
285
295
|
});
|
|
286
296
|
});
|
|
287
|
-
|
|
297
|
+
x.displayName = "Combobox";
|
|
288
298
|
//#endregion
|
|
289
|
-
export {
|
|
299
|
+
export { x as Combobox, h as comboboxTriggerVariants };
|