eidos-ui 2.1.0 → 3.1.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/README.md +66 -16
- package/dist/ThemeProvider.types-DgXN0gEH.d.cts +88 -0
- package/dist/ThemeProvider.types-DgXN0gEH.d.ts +88 -0
- package/dist/chunk-2ZY7M72Q.js +521 -0
- package/dist/chunk-2ZY7M72Q.js.map +1 -0
- package/dist/{chunk-W6IKHJ76.cjs → chunk-5BX4Q76D.cjs} +134 -126
- package/dist/chunk-5BX4Q76D.cjs.map +1 -0
- package/dist/{chunk-RAZRQ57B.js → chunk-74MBKLYI.js} +97 -16
- package/dist/chunk-74MBKLYI.js.map +1 -0
- package/dist/chunk-H5HWFOWZ.js +390 -0
- package/dist/chunk-H5HWFOWZ.js.map +1 -0
- package/dist/{chunk-VHQTDITV.cjs → chunk-KQD7CQ4Z.cjs} +96 -15
- package/dist/chunk-KQD7CQ4Z.cjs.map +1 -0
- package/dist/{chunk-JV7Z3D3U.js → chunk-LEMCJW57.js} +134 -126
- package/dist/chunk-LEMCJW57.js.map +1 -0
- package/dist/chunk-SE7MWOC7.cjs +390 -0
- package/dist/chunk-SE7MWOC7.cjs.map +1 -0
- package/dist/chunk-U5FHQ73U.cjs +521 -0
- package/dist/chunk-U5FHQ73U.cjs.map +1 -0
- package/dist/color-picker/index.cjs +2 -2
- package/dist/color-picker/index.js +1 -1
- package/dist/fonts/JetBrains-Mono-OFL.txt +93 -0
- package/dist/fonts/Plus-Jakarta-Sans-OFL.txt +93 -0
- package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts.css +32 -0
- package/dist/fonts.css.d.ts +2 -0
- package/dist/index.cjs +32 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +467 -123
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +35 -9
- package/dist/tabs/index.cjs +2 -2
- package/dist/tabs/index.d.cts +11 -0
- package/dist/tabs/index.d.ts +11 -0
- package/dist/tabs/index.js +1 -1
- package/dist/theme-editor/index.cjs +22 -0
- package/dist/theme-editor/index.cjs.map +1 -0
- package/dist/theme-editor/index.d.cts +65 -0
- package/dist/theme-editor/index.d.ts +65 -0
- package/dist/theme-editor/index.js +22 -0
- package/dist/theme-editor/index.js.map +1 -0
- package/dist/theme-provider/index.cjs +27 -0
- package/dist/theme-provider/index.cjs.map +1 -0
- package/dist/theme-provider/index.d.cts +123 -0
- package/dist/theme-provider/index.d.ts +123 -0
- package/dist/theme-provider/index.js +27 -0
- package/dist/theme-provider/index.js.map +1 -0
- package/package.json +13 -3
- package/dist/chunk-JV7Z3D3U.js.map +0 -1
- package/dist/chunk-RAZRQ57B.js.map +0 -1
- package/dist/chunk-VHQTDITV.cjs.map +0 -1
- package/dist/chunk-W6IKHJ76.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/eidos-ui/eidos-ui/dist/chunk-KQD7CQ4Z.cjs","../src/components/Tabs/Tabs.component.tsx"],"names":[],"mappings":"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","file":"/home/runner/work/eidos-ui/eidos-ui/dist/chunk-KQD7CQ4Z.cjs","sourcesContent":[null,"import React, { useState, useRef, useContext, useEffect, useLayoutEffect } from 'react';\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { renderIcon } from '../../utils';\nimport type { TabsProps, TabProps, TabPanelProps, TabsContextValue } from './Tabs.types';\n\n// ============================================================================\n// CONTEXT\n// ============================================================================\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null);\n\nconst useTabsContext = (): TabsContextValue => {\n const ctx = useContext(TabsContext);\n if (!ctx) throw new Error('Tab/TabPanel must be used inside <Tabs>');\n return ctx;\n};\n\n// ============================================================================\n// TAB - individual tab trigger button\n// Defined before Tabs so Tabs can use `child.type === Tab` for child separation.\n// ============================================================================\n\nexport const Tab: React.FC<TabProps> = ({\n value,\n children,\n disabled = false,\n icon,\n className = '',\n}) => {\n const { activeValue, onSelect, size, fullWidth, listRef } = useTabsContext();\n const isActive = activeValue === value;\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n const list = listRef.current;\n if (!list) return;\n\n const allTabs = Array.from(\n list.querySelectorAll('[role=\"tab\"]:not([disabled])'),\n ) as HTMLElement[];\n const currentIndex = allTabs.indexOf(e.currentTarget);\n if (currentIndex === -1) return;\n\n let targetIndex = -1;\n if (e.key === 'ArrowRight') targetIndex = (currentIndex + 1) % allTabs.length;\n else if (e.key === 'ArrowLeft')\n targetIndex = (currentIndex - 1 + allTabs.length) % allTabs.length;\n else if (e.key === 'Home') targetIndex = 0;\n else if (e.key === 'End') targetIndex = allTabs.length - 1;\n\n if (targetIndex !== -1) {\n e.preventDefault();\n allTabs[targetIndex].focus();\n }\n };\n\n const tabClasses = [\n 'eidos-tab',\n `eidos-tab--${size}`,\n isActive && 'eidos-tab--active',\n disabled && 'eidos-tab--disabled',\n fullWidth && 'eidos-tab--fullWidth',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button\n id={`eidos-tab-${value}`}\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={`eidos-tabpanel-${value}`}\n tabIndex={isActive ? 0 : -1}\n disabled={disabled}\n className={tabClasses}\n onClick={() => !disabled && onSelect(value)}\n onKeyDown={handleKeyDown}\n type=\"button\"\n >\n {icon && <span className=\"eidos-tab-icon\">{renderIcon(icon, 'eidos-tab-icon-svg')}</span>}\n <span className=\"eidos-tab-label\">{children}</span>\n </button>\n );\n};\n\nTab.displayName = 'Tab';\n\n// ============================================================================\n// TAB PANEL - content region shown when its value matches the active tab\n// Defined before Tabs for the same `child.type === TabPanel` check.\n// ============================================================================\n\nexport const TabPanel: React.FC<TabPanelProps> = ({ value, children, className = '' }) => {\n const { activeValue } = useTabsContext();\n const isActive = activeValue === value;\n\n if (!isActive) return null;\n\n return (\n <div\n id={`eidos-tabpanel-${value}`}\n role=\"tabpanel\"\n aria-labelledby={`eidos-tab-${value}`}\n tabIndex={0}\n className={['eidos-tab-panel', className].filter(Boolean).join(' ')}\n >\n {children}\n </div>\n );\n};\n\nTabPanel.displayName = 'TabPanel';\n\n// ============================================================================\n// TABS - root container; provides context, separates tab/panel children\n// ============================================================================\n\nexport const Tabs: React.FC<TabsProps> = ({\n value,\n defaultValue,\n onChange,\n variant = 'line',\n size = 'md',\n color = 'primary',\n fullWidth = false,\n scrollButtons = 'auto',\n className = '',\n children,\n}) => {\n const isControlled = value !== undefined;\n const [localValue, setLocalValue] = useState(defaultValue ?? '');\n const activeValue = isControlled ? value! : localValue;\n\n // Separate Tab and TabPanel children so the list and panels render in\n // distinct DOM regions, regardless of how the consumer orders them.\n const tabChildren: React.ReactElement[] = [];\n const panelChildren: React.ReactElement[] = [];\n\n React.Children.forEach(children, (child) => {\n if (!React.isValidElement(child)) return;\n if (child.type === Tab) {\n tabChildren.push(child);\n } else if (child.type === TabPanel) {\n panelChildren.push(child);\n }\n });\n\n const listRef = useRef<HTMLDivElement>(null);\n const indicatorRef = useRef<HTMLSpanElement>(null);\n // Tracks whether the indicator has been positioned at least once so we can\n // skip the CSS transition on the very first render and avoid it animating\n // from the top-left corner to the initial tab.\n const hasPositioned = useRef(false);\n\n useLayoutEffect(() => {\n if (variant !== 'line') return;\n const list = listRef.current;\n const indicator = indicatorRef.current;\n if (!list || !indicator) return;\n\n const activeTab = list.querySelector('[aria-selected=\"true\"]') as HTMLElement | null;\n if (!activeTab) return;\n\n // Suppress the CSS transition on the initial paint so the indicator snaps\n // into place rather than sliding from 0.\n if (!hasPositioned.current) {\n indicator.style.transition = 'none';\n }\n\n indicator.style.left = `${activeTab.offsetLeft}px`;\n indicator.style.width = `${activeTab.offsetWidth}px`;\n\n if (!hasPositioned.current) {\n // Force a synchronous reflow so the browser commits the no-transition\n // position before we re-enable the transition for future clicks.\n void indicator.offsetWidth;\n indicator.style.transition = '';\n hasPositioned.current = true;\n }\n }, [activeValue, variant, fullWidth]);\n\n // The list scrolls horizontally when the strip is wider than its container,\n // so an activated tab can sit outside the scrollport - reachable by keyboard\n // (`End`) or by a controlled `value` change, but invisible. `scrollLeft` is\n // adjusted directly rather than via `scrollIntoView`, which walks the whole\n // ancestor chain and would scroll the page vertically when the strip is below\n // the fold.\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!list) return;\n\n const activeTab = list.querySelector('[aria-selected=\"true\"]') as HTMLElement | null;\n if (!activeTab) return;\n\n const left = activeTab.offsetLeft;\n const right = left + activeTab.offsetWidth;\n\n if (left < list.scrollLeft) {\n list.scrollLeft = left;\n } else if (right > list.scrollLeft + list.clientWidth) {\n list.scrollLeft = right - list.clientWidth;\n }\n }, [activeValue]);\n\n // Whether either end of the strip has content hidden past it. Drives both\n // the presence of the scroll buttons (neither end scrollable = the strip\n // fits, so no buttons) and their disabled state at the extremes.\n const [scrollState, setScrollState] = useState({ canScrollPrev: false, canScrollNext: false });\n const hasScrollButtons = scrollButtons !== 'none';\n\n useEffect(() => {\n if (!hasScrollButtons) return;\n const list = listRef.current;\n if (!list) return;\n\n const update = () => {\n const maxScroll = list.scrollWidth - list.clientWidth;\n // 1px of tolerance: fractional layout widths leave a sub-pixel remainder\n // at either end that would otherwise keep a button enabled for a scroll\n // that can no longer move anything.\n const canScrollPrev = list.scrollLeft > 1;\n const canScrollNext = list.scrollLeft < maxScroll - 1;\n setScrollState((previous) =>\n previous.canScrollPrev === canScrollPrev && previous.canScrollNext === canScrollNext\n ? previous\n : { canScrollPrev, canScrollNext },\n );\n };\n\n update();\n list.addEventListener('scroll', update, { passive: true });\n\n // The list's own box stays the same width when a tab's label reflows or a\n // font finishes loading, so the tabs have to be observed as well as the\n // container - only their sizes tell us the strip started overflowing.\n const observer = new ResizeObserver(update);\n observer.observe(list);\n Array.from(list.children).forEach((child) => observer.observe(child));\n\n return () => {\n list.removeEventListener('scroll', update);\n observer.disconnect();\n };\n }, [hasScrollButtons, tabChildren.length, size, variant, fullWidth]);\n\n const scrollByStep = (direction: -1 | 1) => {\n const list = listRef.current;\n if (!list) return;\n\n // A step just short of a full page keeps a tab of context on screen, the\n // same way a paged scrollbar click does.\n const step = list.clientWidth * 0.8;\n const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n list.scrollBy({ left: direction * step, behavior: reducedMotion ? 'auto' : 'smooth' });\n };\n\n const onSelect = (newValue: string) => {\n if (!isControlled) {\n setLocalValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const rootClasses = ['eidos-tabs', `eidos-tabs--${variant}`, `eidos-tabs--${color}`, className]\n .filter(Boolean)\n .join(' ');\n\n const listClasses = [\n 'eidos-tabs-list',\n `eidos-tabs-list--${size}`,\n fullWidth && 'eidos-tabs-list--fullWidth',\n // With buttons, they are the affordance - a native scrollbar underneath\n // them is redundant, and on a space-taking one it would also sit over the\n // `line` variant's rule.\n hasScrollButtons && 'eidos-tabs-list--hideScrollbar',\n ]\n .filter(Boolean)\n .join(' ');\n\n // Each button exists only while its own direction has somewhere to go: none\n // at all when the strip fits, and none at the end you have reached. A\n // disabled button would be pointing at nothing. They are positioned\n // absolutely, so appearing and disappearing never moves the tabs.\n const showPrevButton = hasScrollButtons && scrollState.canScrollPrev;\n const showNextButton = hasScrollButtons && scrollState.canScrollNext;\n\n const scrollButtonClasses = (direction: 'prev' | 'next') =>\n [\n 'eidos-tabs-scroll-button',\n `eidos-tabs-scroll-button--${direction}`,\n `eidos-tabs-scroll-button--${size}`,\n ].join(' ');\n\n const contextValue: TabsContextValue = {\n activeValue,\n onSelect,\n variant,\n size,\n color,\n fullWidth,\n listRef,\n };\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div className={rootClasses}>\n {/* The buttons are siblings of the tab list, never children of it:\n `role=\"tablist\"` only accepts tabs. They are also hidden from\n assistive tech and skipped by Tab, because they are a pointer\n affordance for something the keyboard already does - arrow keys\n move between tabs and scroll the active one into view. */}\n <div className=\"eidos-tabs-bar\">\n {showPrevButton && (\n <button\n type=\"button\"\n className={scrollButtonClasses('prev')}\n onClick={() => scrollByStep(-1)}\n tabIndex={-1}\n aria-hidden=\"true\"\n >\n <ChevronLeft className=\"eidos-tabs-scroll-button-icon\" />\n </button>\n )}\n\n <div ref={listRef} className={listClasses} role=\"tablist\">\n {tabChildren}\n {variant === 'line' && (\n <span ref={indicatorRef} className=\"eidos-tabs-indicator\" aria-hidden=\"true\" />\n )}\n </div>\n\n {showNextButton && (\n <button\n type=\"button\"\n className={scrollButtonClasses('next')}\n onClick={() => scrollByStep(1)}\n tabIndex={-1}\n aria-hidden=\"true\"\n >\n <ChevronRight className=\"eidos-tabs-scroll-button-icon\" />\n </button>\n )}\n </div>\n\n <div className=\"eidos-tabs-panels\">{panelChildren}</div>\n </div>\n </TabsContext.Provider>\n );\n};\n\nTabs.displayName = 'Tabs';\n"]}
|
|
@@ -73,7 +73,7 @@ function rgbToHsv(r, g, b) {
|
|
|
73
73
|
h = h * 60;
|
|
74
74
|
if (h < 0) h += 360;
|
|
75
75
|
}
|
|
76
|
-
return { h
|
|
76
|
+
return { h, s, v };
|
|
77
77
|
}
|
|
78
78
|
function rgbToHex(r, g, b) {
|
|
79
79
|
const ch = (n) => Math.round(Math.max(0, Math.min(255, n))).toString(16).padStart(2, "0");
|
|
@@ -342,137 +342,145 @@ var ColorPicker = ({
|
|
|
342
342
|
backgroundSize: "100%, 8px 8px, 8px 8px, 8px 8px, 8px 8px",
|
|
343
343
|
backgroundPosition: "0 0, 0 0, 0 4px, 4px -4px, -4px 0"
|
|
344
344
|
};
|
|
345
|
-
const panel = /* @__PURE__ */ jsxs(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
{
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
style: {
|
|
352
|
-
background: [
|
|
353
|
-
"linear-gradient(to top, #000, transparent)",
|
|
354
|
-
`linear-gradient(to right, #fff, hsl(${hsv.h}, 100%, 50%))`
|
|
355
|
-
].join(", ")
|
|
356
|
-
},
|
|
357
|
-
onMouseDown: handleCanvasMouseDown,
|
|
358
|
-
role: "presentation",
|
|
359
|
-
children: /* @__PURE__ */ jsx(
|
|
345
|
+
const panel = /* @__PURE__ */ jsxs(
|
|
346
|
+
"div",
|
|
347
|
+
{
|
|
348
|
+
className: `eidos-color-picker-panel eidos-color-picker-panel--${size}${inline ? " eidos-color-picker-panel--inline" : ""}`,
|
|
349
|
+
children: [
|
|
350
|
+
/* @__PURE__ */ jsx(
|
|
360
351
|
"div",
|
|
361
352
|
{
|
|
362
|
-
|
|
353
|
+
ref: canvasRef,
|
|
354
|
+
className: "eidos-color-picker-canvas",
|
|
363
355
|
style: {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
356
|
+
background: [
|
|
357
|
+
"linear-gradient(to top, #000, transparent)",
|
|
358
|
+
`linear-gradient(to right, #fff, hsl(${hsv.h}, 100%, 50%))`
|
|
359
|
+
].join(", ")
|
|
360
|
+
},
|
|
361
|
+
onMouseDown: handleCanvasMouseDown,
|
|
362
|
+
role: "presentation",
|
|
363
|
+
children: /* @__PURE__ */ jsx(
|
|
364
|
+
"div",
|
|
365
|
+
{
|
|
366
|
+
className: "eidos-color-picker-thumb",
|
|
367
|
+
style: {
|
|
368
|
+
// Rounded for display only - hsv.s/v are unrounded floats so the
|
|
369
|
+
// hex round trip stays lossless (see rgbToHsv).
|
|
370
|
+
left: `${hsv.s.toFixed(2)}%`,
|
|
371
|
+
top: `${(100 - hsv.v).toFixed(2)}%`,
|
|
372
|
+
background: currentHex
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
)
|
|
368
376
|
}
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
377
|
+
),
|
|
378
|
+
/* @__PURE__ */ jsxs("div", { className: "eidos-color-picker-sliders", children: [
|
|
379
|
+
/* @__PURE__ */ jsx(
|
|
380
|
+
"input",
|
|
381
|
+
{
|
|
382
|
+
type: "range",
|
|
383
|
+
className: "eidos-color-picker-hue",
|
|
384
|
+
min: 0,
|
|
385
|
+
max: 360,
|
|
386
|
+
step: 1,
|
|
387
|
+
value: hsv.h,
|
|
388
|
+
disabled,
|
|
389
|
+
onChange: handleHueChange,
|
|
390
|
+
"aria-label": "Hue"
|
|
391
|
+
}
|
|
392
|
+
),
|
|
393
|
+
showAlpha && /* @__PURE__ */ jsxs("div", { className: "eidos-color-picker-alpha-wrapper", children: [
|
|
394
|
+
/* @__PURE__ */ jsx("div", { className: "eidos-color-picker-alpha-bg", style: alphaTrackBg }),
|
|
395
|
+
/* @__PURE__ */ jsx(
|
|
396
|
+
"input",
|
|
397
|
+
{
|
|
398
|
+
type: "range",
|
|
399
|
+
className: "eidos-color-picker-alpha",
|
|
400
|
+
min: 0,
|
|
401
|
+
max: 100,
|
|
402
|
+
step: 1,
|
|
403
|
+
value: Math.round(alpha * 100),
|
|
404
|
+
disabled,
|
|
405
|
+
onChange: handleAlphaChange,
|
|
406
|
+
"aria-label": "Opacity"
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
] })
|
|
410
|
+
] }),
|
|
411
|
+
/* @__PURE__ */ jsxs("div", { className: "eidos-color-picker-inputs", children: [
|
|
412
|
+
/* @__PURE__ */ jsx("div", { className: "eidos-color-picker-format-btns", role: "group", "aria-label": "Colour format", children: ["hex", "rgb", "hsl"].map((fmt) => /* @__PURE__ */ jsx(
|
|
413
|
+
"button",
|
|
414
|
+
{
|
|
415
|
+
type: "button",
|
|
416
|
+
className: [
|
|
417
|
+
"eidos-color-picker-format-btn",
|
|
418
|
+
activeFormat === fmt && "eidos-color-picker-format-btn--active"
|
|
419
|
+
].filter(Boolean).join(" "),
|
|
420
|
+
onClick: () => handleFormatChange(fmt),
|
|
421
|
+
disabled,
|
|
422
|
+
"aria-pressed": activeFormat === fmt,
|
|
423
|
+
children: fmt.toUpperCase()
|
|
424
|
+
},
|
|
425
|
+
fmt
|
|
426
|
+
)) }),
|
|
427
|
+
/* @__PURE__ */ jsx(
|
|
428
|
+
"input",
|
|
429
|
+
{
|
|
430
|
+
type: "text",
|
|
431
|
+
className: "eidos-color-picker-input",
|
|
432
|
+
value: inputText,
|
|
433
|
+
disabled,
|
|
434
|
+
spellCheck: false,
|
|
435
|
+
"aria-label": "Colour value",
|
|
436
|
+
onChange: (e) => setInputText(e.target.value),
|
|
437
|
+
onFocus: () => {
|
|
438
|
+
inputFocusedRef.current = true;
|
|
439
|
+
},
|
|
440
|
+
onBlur: () => {
|
|
441
|
+
inputFocusedRef.current = false;
|
|
442
|
+
handleInputCommit();
|
|
443
|
+
},
|
|
444
|
+
onKeyDown: (e) => {
|
|
445
|
+
if (e.key === "Enter") handleInputCommit();
|
|
446
|
+
if (e.key === "Escape") {
|
|
447
|
+
setInputText(colorToText(hsvRef.current, alphaRef.current, activeFormatRef.current));
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
),
|
|
452
|
+
/* @__PURE__ */ jsx(
|
|
453
|
+
"button",
|
|
454
|
+
{
|
|
455
|
+
type: "button",
|
|
456
|
+
className: ["eidos-color-picker-copy", copied && "eidos-color-picker-copy--copied"].filter(Boolean).join(" "),
|
|
457
|
+
onClick: handleCopy,
|
|
458
|
+
disabled,
|
|
459
|
+
"aria-label": "Copy colour value",
|
|
460
|
+
title: "Copy colour value",
|
|
461
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 })
|
|
462
|
+
}
|
|
463
|
+
)
|
|
464
|
+
] }),
|
|
465
|
+
showSwatches && /* @__PURE__ */ jsx("div", { className: "eidos-color-picker-swatches", role: "group", "aria-label": "Colour presets", children: swatches.map((swatchHex) => /* @__PURE__ */ jsx(
|
|
466
|
+
"button",
|
|
391
467
|
{
|
|
392
|
-
type: "
|
|
393
|
-
className:
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
468
|
+
type: "button",
|
|
469
|
+
className: [
|
|
470
|
+
"eidos-color-picker-swatch",
|
|
471
|
+
currentHex === swatchHex && "eidos-color-picker-swatch--active"
|
|
472
|
+
].filter(Boolean).join(" "),
|
|
473
|
+
style: { background: swatchHex },
|
|
474
|
+
onClick: () => handleSwatchClick(swatchHex),
|
|
398
475
|
disabled,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
)
|
|
403
|
-
] })
|
|
404
|
-
] }),
|
|
405
|
-
/* @__PURE__ */ jsxs("div", { className: "eidos-color-picker-inputs", children: [
|
|
406
|
-
/* @__PURE__ */ jsx("div", { className: "eidos-color-picker-format-btns", role: "group", "aria-label": "Colour format", children: ["hex", "rgb", "hsl"].map((fmt) => /* @__PURE__ */ jsx(
|
|
407
|
-
"button",
|
|
408
|
-
{
|
|
409
|
-
type: "button",
|
|
410
|
-
className: [
|
|
411
|
-
"eidos-color-picker-format-btn",
|
|
412
|
-
activeFormat === fmt && "eidos-color-picker-format-btn--active"
|
|
413
|
-
].filter(Boolean).join(" "),
|
|
414
|
-
onClick: () => handleFormatChange(fmt),
|
|
415
|
-
disabled,
|
|
416
|
-
"aria-pressed": activeFormat === fmt,
|
|
417
|
-
children: fmt.toUpperCase()
|
|
418
|
-
},
|
|
419
|
-
fmt
|
|
420
|
-
)) }),
|
|
421
|
-
/* @__PURE__ */ jsx(
|
|
422
|
-
"input",
|
|
423
|
-
{
|
|
424
|
-
type: "text",
|
|
425
|
-
className: "eidos-color-picker-input",
|
|
426
|
-
value: inputText,
|
|
427
|
-
disabled,
|
|
428
|
-
spellCheck: false,
|
|
429
|
-
"aria-label": "Colour value",
|
|
430
|
-
onChange: (e) => setInputText(e.target.value),
|
|
431
|
-
onFocus: () => {
|
|
432
|
-
inputFocusedRef.current = true;
|
|
433
|
-
},
|
|
434
|
-
onBlur: () => {
|
|
435
|
-
inputFocusedRef.current = false;
|
|
436
|
-
handleInputCommit();
|
|
476
|
+
"aria-label": `Select ${swatchHex}`,
|
|
477
|
+
title: swatchHex
|
|
437
478
|
},
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
),
|
|
446
|
-
/* @__PURE__ */ jsx(
|
|
447
|
-
"button",
|
|
448
|
-
{
|
|
449
|
-
type: "button",
|
|
450
|
-
className: ["eidos-color-picker-copy", copied && "eidos-color-picker-copy--copied"].filter(Boolean).join(" "),
|
|
451
|
-
onClick: handleCopy,
|
|
452
|
-
disabled,
|
|
453
|
-
"aria-label": "Copy colour value",
|
|
454
|
-
title: "Copy colour value",
|
|
455
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 })
|
|
456
|
-
}
|
|
457
|
-
)
|
|
458
|
-
] }),
|
|
459
|
-
showSwatches && /* @__PURE__ */ jsx("div", { className: "eidos-color-picker-swatches", role: "group", "aria-label": "Colour presets", children: swatches.map((swatchHex) => /* @__PURE__ */ jsx(
|
|
460
|
-
"button",
|
|
461
|
-
{
|
|
462
|
-
type: "button",
|
|
463
|
-
className: [
|
|
464
|
-
"eidos-color-picker-swatch",
|
|
465
|
-
currentHex === swatchHex && "eidos-color-picker-swatch--active"
|
|
466
|
-
].filter(Boolean).join(" "),
|
|
467
|
-
style: { background: swatchHex },
|
|
468
|
-
onClick: () => handleSwatchClick(swatchHex),
|
|
469
|
-
disabled,
|
|
470
|
-
"aria-label": `Select ${swatchHex}`,
|
|
471
|
-
title: swatchHex
|
|
472
|
-
},
|
|
473
|
-
swatchHex
|
|
474
|
-
)) })
|
|
475
|
-
] });
|
|
479
|
+
swatchHex
|
|
480
|
+
)) })
|
|
481
|
+
]
|
|
482
|
+
}
|
|
483
|
+
);
|
|
476
484
|
const rootClasses = [
|
|
477
485
|
"eidos-color-picker",
|
|
478
486
|
`eidos-color-picker--${size}`,
|
|
@@ -523,4 +531,4 @@ ColorPicker.displayName = "ColorPicker";
|
|
|
523
531
|
export {
|
|
524
532
|
ColorPicker
|
|
525
533
|
};
|
|
526
|
-
//# sourceMappingURL=chunk-
|
|
534
|
+
//# sourceMappingURL=chunk-LEMCJW57.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ColorPicker/ColorPicker.component.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { Dropdown } from '../Dropdown/Dropdown.component';\nimport type {\n ColorPickerProps,\n HSVColor,\n RGBColor,\n HSLColor,\n ColorFormat,\n} from './ColorPicker.types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_SWATCHES: string[] = [\n '#ef4444',\n '#f97316',\n '#f59e0b',\n '#10b981',\n '#06b6d4',\n '#6366f1',\n '#8b5cf6',\n '#ec4899',\n '#64748b',\n '#1e293b',\n];\n\n// ============================================================================\n// Pure colour-utility functions\n// ============================================================================\n\nfunction hsvToRgb(h: number, s: number, v: number): RGBColor {\n // h: 0–360, s: 0–100, v: 0–100 → r,g,b: 0–255\n const sn = s / 100;\n const vn = v / 100;\n const c = vn * sn;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = vn - c;\n\n let r: number, g: number, b: number;\n if (h < 60) {\n r = c;\n g = x;\n b = 0;\n } else if (h < 120) {\n r = x;\n g = c;\n b = 0;\n } else if (h < 180) {\n r = 0;\n g = c;\n b = x;\n } else if (h < 240) {\n r = 0;\n g = x;\n b = c;\n } else if (h < 300) {\n r = x;\n g = 0;\n b = c;\n } else {\n r = c;\n g = 0;\n b = x;\n }\n\n return {\n r: Math.round((r + m) * 255),\n g: Math.round((g + m) * 255),\n b: Math.round((b + m) * 255),\n };\n}\n\nfunction rgbToHsv(r: number, g: number, b: number): HSVColor {\n // r,g,b: 0–255 → h: 0–360, s: 0–100, v: 0–100\n const rn = r / 255;\n const gn = g / 255;\n const bn = b / 255;\n\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const delta = max - min;\n\n const v = max * 100;\n const s = max === 0 ? 0 : (delta / max) * 100;\n\n let h = 0;\n if (delta !== 0) {\n if (max === rn) h = ((gn - bn) / delta) % 6;\n else if (max === gn) h = (bn - rn) / delta + 2;\n else h = (rn - gn) / delta + 4;\n h = h * 60;\n if (h < 0) h += 360;\n }\n\n // Deliberately NOT rounded. HSV is this component's internal state, and\n // rounding s/v to whole percent makes the hex -> HSV -> hex round trip lossy:\n // `#5c5de8` came back as `#5d5de8`, so a controlled `value` displayed a\n // different colour than the one passed in, and any interaction committed the\n // drifted value. `hsvToRgb` already rounds to whole channels at the end, so\n // precision is only needed in between. Every consumer of these floats (the\n // hue gradient, the thumb offsets, the hue slider) accepts them.\n return { h, s, v };\n}\n\nfunction rgbToHex(r: number, g: number, b: number): string {\n const ch = (n: number) =>\n Math.round(Math.max(0, Math.min(255, n)))\n .toString(16)\n .padStart(2, '0');\n return `#${ch(r)}${ch(g)}${ch(b)}`;\n}\n\nfunction hexToRgb(hex: string): RGBColor | null {\n const c = hex.trim().replace(/^#/, '');\n let r: number, g: number, b: number;\n\n if (c.length === 3) {\n r = parseInt(c[0] + c[0], 16);\n g = parseInt(c[1] + c[1], 16);\n b = parseInt(c[2] + c[2], 16);\n } else if (c.length === 6) {\n r = parseInt(c.slice(0, 2), 16);\n g = parseInt(c.slice(2, 4), 16);\n b = parseInt(c.slice(4, 6), 16);\n } else {\n return null;\n }\n\n if (isNaN(r) || isNaN(g) || isNaN(b)) return null;\n return { r, g, b };\n}\n\nfunction rgbToHsl(r: number, g: number, b: number): HSLColor {\n // r,g,b: 0–255 → h: 0–360, s: 0–100, l: 0–100\n const rn = r / 255;\n const gn = g / 255;\n const bn = b / 255;\n\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const delta = max - min;\n const l = (max + min) / 2;\n\n let h = 0;\n let s = 0;\n\n if (delta !== 0) {\n s = delta / (1 - Math.abs(2 * l - 1));\n if (max === rn) h = ((gn - bn) / delta) % 6;\n else if (max === gn) h = (bn - rn) / delta + 2;\n else h = (rn - gn) / delta + 4;\n h = h * 60;\n if (h < 0) h += 360;\n }\n\n return { h: Math.round(h), s: Math.round(s * 100), l: Math.round(l * 100) };\n}\n\nfunction hslToRgb(h: number, s: number, l: number): RGBColor {\n // h: 0–360, s: 0–100, l: 0–100 → r,g,b: 0–255\n const sn = s / 100;\n const ln = l / 100;\n const c = (1 - Math.abs(2 * ln - 1)) * sn;\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1));\n const m = ln - c / 2;\n\n let r: number, g: number, b: number;\n if (h < 60) {\n r = c;\n g = x;\n b = 0;\n } else if (h < 120) {\n r = x;\n g = c;\n b = 0;\n } else if (h < 180) {\n r = 0;\n g = c;\n b = x;\n } else if (h < 240) {\n r = 0;\n g = x;\n b = c;\n } else if (h < 300) {\n r = x;\n g = 0;\n b = c;\n } else {\n r = c;\n g = 0;\n b = x;\n }\n\n return {\n r: Math.round((r + m) * 255),\n g: Math.round((g + m) * 255),\n b: Math.round((b + m) * 255),\n };\n}\n\n// ============================================================================\n// Format helpers\n// ============================================================================\n\nfunction colorToText(hsv: HSVColor, alpha: number, fmt: ColorFormat): string {\n const rgb = hsvToRgb(hsv.h, hsv.s, hsv.v);\n\n switch (fmt) {\n case 'hex':\n return rgbToHex(rgb.r, rgb.g, rgb.b);\n case 'rgb':\n return alpha < 1\n ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha.toFixed(2)})`\n : `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;\n case 'hsl': {\n const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);\n return alpha < 1\n ? `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${alpha.toFixed(2)})`\n : `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;\n }\n }\n}\n\nfunction parseColorText(text: string): RGBColor | null {\n const t = text.trim();\n\n // Try hex (with or without leading #)\n const hexCandidate = t.startsWith('#') ? t : /^[0-9a-f]{3,6}$/i.test(t) ? `#${t}` : null;\n if (hexCandidate) return hexToRgb(hexCandidate);\n\n // Try rgb() / rgba()\n const rgbMatch = t.match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/i);\n if (rgbMatch) {\n return {\n r: parseInt(rgbMatch[1], 10),\n g: parseInt(rgbMatch[2], 10),\n b: parseInt(rgbMatch[3], 10),\n };\n }\n\n // Try hsl() / hsla()\n const hslMatch = t.match(/hsla?\\(\\s*(\\d+)\\s*,\\s*(\\d+)%?\\s*,\\s*(\\d+)%?/i);\n if (hslMatch) {\n return hslToRgb(\n parseInt(hslMatch[1], 10),\n parseInt(hslMatch[2], 10),\n parseInt(hslMatch[3], 10),\n );\n }\n\n return null;\n}\n\n/** Parse a hex string to HSVColor, falling back to red on failure. */\nfunction hexToHsv(hex: string): HSVColor {\n const rgb = hexToRgb(hex);\n return rgb ? rgbToHsv(rgb.r, rgb.g, rgb.b) : { h: 0, s: 100, v: 100 };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({\n value,\n defaultValue,\n onChange,\n format = 'hex',\n showAlpha = false,\n showSwatches = true,\n swatches = DEFAULT_SWATCHES,\n disabled = false,\n size = 'md',\n inline = false,\n label,\n className = '',\n}) => {\n // ── Initial hex (only used on first render by useState) ──────────────────\n const initialHex = value ?? defaultValue ?? '#6366f1';\n\n // ── State ─────────────────────────────────────────────────────────────────\n const [hsv, setHsv] = useState<HSVColor>(() => hexToHsv(initialHex));\n const [alpha, setAlpha] = useState<number>(1);\n const [activeFormat, setActiveFormat] = useState<ColorFormat>(format);\n const [inputText, setInputText] = useState<string>(() =>\n colorToText(hexToHsv(initialHex), 1, format),\n );\n const [copied, setCopied] = useState(false);\n\n // ── Refs - give event handlers always-fresh values without stale closures ──\n const hsvRef = useRef<HSVColor>(hsv);\n hsvRef.current = hsv;\n\n const alphaRef = useRef<number>(alpha);\n alphaRef.current = alpha;\n\n const activeFormatRef = useRef<ColorFormat>(activeFormat);\n activeFormatRef.current = activeFormat;\n\n // onChange is stored in a ref so applyColor never becomes stale\n const onChangeRef = useRef<ColorPickerProps['onChange']>(onChange);\n onChangeRef.current = onChange;\n\n const inputFocusedRef = useRef(false);\n const canvasRef = useRef<HTMLDivElement>(null);\n\n // Refs for in-flight drag listeners - cleaned up on mouseup and on unmount\n const dragHandlersRef = useRef<{\n move: (e: MouseEvent) => void;\n up: () => void;\n } | null>(null);\n\n const copiedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // ── Derived ───────────────────────────────────────────────────────────────\n const currentRgb = hsvToRgb(hsv.h, hsv.s, hsv.v);\n const currentHex = rgbToHex(currentRgb.r, currentRgb.g, currentRgb.b);\n\n // ── Sync from controlled `value` prop ─────────────────────────────────────\n // Runs only when `value` changes. We normalize both sides to the same\n // hex format before comparing so that round-trip conversions don't trigger\n // spurious updates (which would overwrite the preserved hue when s/v = 0).\n useEffect(() => {\n if (value === undefined) return;\n const rgb = hexToRgb(value);\n if (!rgb) return;\n const newHsv = rgbToHsv(rgb.r, rgb.g, rgb.b);\n const newNormalised = rgbToHex(\n ...(Object.values(hsvToRgb(newHsv.h, newHsv.s, newHsv.v)) as [number, number, number]),\n );\n // currentHex is captured from this render - guards against echo loops\n // when the parent echoes back our own onChange emission\n if (newNormalised === currentHex) return;\n setHsv(newHsv);\n if (!inputFocusedRef.current) {\n setInputText(colorToText(newHsv, alphaRef.current, activeFormatRef.current));\n }\n }, [value, currentHex]);\n\n // ── Cleanup drag listeners and timers on unmount ──────────────────────────\n useEffect(() => {\n return () => {\n if (dragHandlersRef.current) {\n document.removeEventListener('mousemove', dragHandlersRef.current.move);\n document.removeEventListener('mouseup', dragHandlersRef.current.up);\n }\n if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);\n };\n }, []);\n\n // ── Core: apply a new HSV + alpha, emit onChange ───────────────────────────\n // Stable (empty dep array) - reads live values exclusively via refs.\n const applyColor = useCallback((newHsv: HSVColor, newAlpha: number) => {\n setHsv(newHsv);\n setAlpha(newAlpha);\n\n if (!inputFocusedRef.current) {\n setInputText(colorToText(newHsv, newAlpha, activeFormatRef.current));\n }\n\n const rgb = hsvToRgb(newHsv.h, newHsv.s, newHsv.v);\n const hex = rgbToHex(rgb.r, rgb.g, rgb.b);\n onChangeRef.current?.(hex);\n }, []);\n\n // ── 2-D saturation / brightness canvas ────────────────────────────────────\n const handleCanvasMouseDown = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return;\n e.preventDefault();\n\n const pick = (clientX: number, clientY: number) => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const rect = canvas.getBoundingClientRect();\n const s = Math.max(0, Math.min(100, ((clientX - rect.left) / rect.width) * 100));\n const v = Math.max(0, Math.min(100, 100 - ((clientY - rect.top) / rect.height) * 100));\n applyColor({ h: hsvRef.current.h, s, v }, alphaRef.current);\n };\n\n pick(e.clientX, e.clientY);\n\n const handleMouseMove = (me: MouseEvent) => pick(me.clientX, me.clientY);\n const handleMouseUp = () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n dragHandlersRef.current = null;\n };\n\n dragHandlersRef.current = { move: handleMouseMove, up: handleMouseUp };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n },\n [disabled, applyColor],\n );\n\n // ── Hue slider ────────────────────────────────────────────────────────────\n const handleHueChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n applyColor({ ...hsvRef.current, h: Number(e.target.value) }, alphaRef.current);\n },\n [applyColor],\n );\n\n // ── Alpha slider ──────────────────────────────────────────────────────────\n const handleAlphaChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n applyColor(hsvRef.current, Number(e.target.value) / 100);\n },\n [applyColor],\n );\n\n // ── Format toggle ─────────────────────────────────────────────────────────\n const handleFormatChange = useCallback((fmt: ColorFormat) => {\n setActiveFormat(fmt);\n setInputText(colorToText(hsvRef.current, alphaRef.current, fmt));\n }, []);\n\n // ── Text-input commit (Enter / blur) ──────────────────────────────────────\n const handleInputCommit = useCallback(() => {\n const rgb = parseColorText(inputText);\n if (!rgb) {\n // Invalid - reset to the current valid colour\n setInputText(colorToText(hsvRef.current, alphaRef.current, activeFormatRef.current));\n return;\n }\n const newHsv = rgbToHsv(rgb.r, rgb.g, rgb.b);\n applyColor(newHsv, alphaRef.current);\n // Always normalise the text after a commit (even if the input still has focus)\n setInputText(colorToText(newHsv, alphaRef.current, activeFormatRef.current));\n }, [inputText, applyColor]);\n\n // ── Swatch click ──────────────────────────────────────────────────────────\n const handleSwatchClick = useCallback(\n (hex: string) => {\n const rgb = hexToRgb(hex);\n if (!rgb) return;\n applyColor(rgbToHsv(rgb.r, rgb.g, rgb.b), alphaRef.current);\n },\n [applyColor],\n );\n\n // ── Copy to clipboard ─────────────────────────────────────────────────────\n const handleCopy = useCallback(() => {\n const text = colorToText(hsvRef.current, alphaRef.current, activeFormatRef.current);\n navigator.clipboard\n .writeText(text)\n .then(() => {\n setCopied(true);\n if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);\n copiedTimerRef.current = setTimeout(() => setCopied(false), 2000);\n })\n .catch(() => {\n // Clipboard access denied - silently ignore\n });\n }, []);\n\n // ── Alpha-slider background gradient ─────────────────────────────────────\n // We use a transparent-to-current-colour gradient layered over a checkerboard\n // so the alpha slider always shows the correct colour transition.\n const transparentColor = `rgba(${currentRgb.r}, ${currentRgb.g}, ${currentRgb.b}, 0)`;\n\n const alphaTrackBg = {\n backgroundImage: [\n `linear-gradient(to right, ${transparentColor}, ${currentHex})`,\n 'linear-gradient(45deg, #e2e8f0 25%, transparent 25%)',\n 'linear-gradient(-45deg, #e2e8f0 25%, transparent 25%)',\n 'linear-gradient(45deg, transparent 75%, #e2e8f0 75%)',\n 'linear-gradient(-45deg, transparent 75%, #e2e8f0 75%)',\n ].join(', '),\n backgroundSize: '100%, 8px 8px, 8px 8px, 8px 8px, 8px 8px',\n backgroundPosition: '0 0, 0 0, 0 4px, 4px -4px, -4px 0',\n };\n\n // ── Picker panel (shared between inline and popover modes) ────────────────\n //\n // The size modifier has to live on the panel itself, not only on the root:\n // in popover mode the panel is portaled to document.body by Dropdown, so\n // anything inside it that sized itself off a `.eidos-color-picker--{size}`\n // ancestor matched nothing and collapsed. That is what removed the\n // saturation/brightness canvas entirely from every non-inline picker.\n const panel = (\n <div\n className={`eidos-color-picker-panel eidos-color-picker-panel--${size}${\n inline ? ' eidos-color-picker-panel--inline' : ''\n }`}\n >\n {/* 2-D sat / brightness canvas */}\n <div\n ref={canvasRef}\n className=\"eidos-color-picker-canvas\"\n style={{\n background: [\n 'linear-gradient(to top, #000, transparent)',\n `linear-gradient(to right, #fff, hsl(${hsv.h}, 100%, 50%))`,\n ].join(', '),\n }}\n onMouseDown={handleCanvasMouseDown}\n role=\"presentation\"\n >\n <div\n className=\"eidos-color-picker-thumb\"\n style={{\n // Rounded for display only - hsv.s/v are unrounded floats so the\n // hex round trip stays lossless (see rgbToHsv).\n left: `${hsv.s.toFixed(2)}%`,\n top: `${(100 - hsv.v).toFixed(2)}%`,\n background: currentHex,\n }}\n />\n </div>\n\n {/* Sliders */}\n <div className=\"eidos-color-picker-sliders\">\n {/* Hue */}\n <input\n type=\"range\"\n className=\"eidos-color-picker-hue\"\n min={0}\n max={360}\n step={1}\n value={hsv.h}\n disabled={disabled}\n onChange={handleHueChange}\n aria-label=\"Hue\"\n />\n\n {/* Alpha */}\n {showAlpha && (\n <div className=\"eidos-color-picker-alpha-wrapper\">\n <div className=\"eidos-color-picker-alpha-bg\" style={alphaTrackBg} />\n <input\n type=\"range\"\n className=\"eidos-color-picker-alpha\"\n min={0}\n max={100}\n step={1}\n value={Math.round(alpha * 100)}\n disabled={disabled}\n onChange={handleAlphaChange}\n aria-label=\"Opacity\"\n />\n </div>\n )}\n </div>\n\n {/* Text input + format toggles + copy */}\n <div className=\"eidos-color-picker-inputs\">\n <div className=\"eidos-color-picker-format-btns\" role=\"group\" aria-label=\"Colour format\">\n {(['hex', 'rgb', 'hsl'] as ColorFormat[]).map((fmt) => (\n <button\n key={fmt}\n type=\"button\"\n className={[\n 'eidos-color-picker-format-btn',\n activeFormat === fmt && 'eidos-color-picker-format-btn--active',\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={() => handleFormatChange(fmt)}\n disabled={disabled}\n aria-pressed={activeFormat === fmt}\n >\n {fmt.toUpperCase()}\n </button>\n ))}\n </div>\n\n <input\n type=\"text\"\n className=\"eidos-color-picker-input\"\n value={inputText}\n disabled={disabled}\n spellCheck={false}\n aria-label=\"Colour value\"\n onChange={(e) => setInputText(e.target.value)}\n onFocus={() => {\n inputFocusedRef.current = true;\n }}\n onBlur={() => {\n inputFocusedRef.current = false;\n handleInputCommit();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleInputCommit();\n if (e.key === 'Escape') {\n setInputText(colorToText(hsvRef.current, alphaRef.current, activeFormatRef.current));\n }\n }}\n />\n\n <button\n type=\"button\"\n className={['eidos-color-picker-copy', copied && 'eidos-color-picker-copy--copied']\n .filter(Boolean)\n .join(' ')}\n onClick={handleCopy}\n disabled={disabled}\n aria-label=\"Copy colour value\"\n title=\"Copy colour value\"\n >\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n </div>\n\n {/* Swatches */}\n {showSwatches && (\n <div className=\"eidos-color-picker-swatches\" role=\"group\" aria-label=\"Colour presets\">\n {swatches.map((swatchHex) => (\n <button\n key={swatchHex}\n type=\"button\"\n className={[\n 'eidos-color-picker-swatch',\n currentHex === swatchHex && 'eidos-color-picker-swatch--active',\n ]\n .filter(Boolean)\n .join(' ')}\n style={{ background: swatchHex }}\n onClick={() => handleSwatchClick(swatchHex)}\n disabled={disabled}\n aria-label={`Select ${swatchHex}`}\n title={swatchHex}\n />\n ))}\n </div>\n )}\n </div>\n );\n\n // ── Root element classes ───────────────────────────────────────────────────\n const rootClasses = [\n 'eidos-color-picker',\n `eidos-color-picker--${size}`,\n disabled && 'eidos-color-picker--disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n // ── Inline mode ───────────────────────────────────────────────────────────\n if (inline) {\n return (\n <div className={rootClasses}>\n {label && <span className=\"eidos-color-picker-label\">{label}</span>}\n {panel}\n </div>\n );\n }\n\n // ── Popover (trigger + Dropdown) ──────────────────────────────────────────\n return (\n <div className={rootClasses}>\n {label && <span className=\"eidos-color-picker-label\">{label}</span>}\n <Dropdown\n trigger={\n <button\n type=\"button\"\n className=\"eidos-color-picker-trigger\"\n disabled={disabled}\n aria-label={label ?? 'Open colour picker'}\n >\n <span\n className=\"eidos-color-picker-trigger-swatch\"\n style={{ background: currentHex }}\n />\n <span className=\"eidos-color-picker-trigger-value\">{currentHex}</span>\n </button>\n }\n content={panel}\n placement=\"bottom\"\n autoWidth={false}\n minWidth={260}\n disabled={disabled}\n />\n </div>\n );\n};\n\nColorPicker.displayName = 'ColorPicker';\n"],"mappings":"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","names":[]}
|