colibri-ui 0.8.96 → 0.8.98

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.
Files changed (135) hide show
  1. package/ColorPicker/ColorPicker.d.ts +3 -0
  2. package/ColorPicker/ColorPicker.js +116 -0
  3. package/ColorPicker/ColorPicker.module.css +22 -0
  4. package/ColorPicker/assets/none.png +0 -0
  5. package/ColorPicker/components/ColorPreview/ColorPreview.module.css +23 -0
  6. package/ColorPicker/components/ColorPreview/index.d.ts +10 -0
  7. package/ColorPicker/components/ColorPreview/index.js +29 -0
  8. package/ColorPicker/components/CustomColorModal/CustomColorModal.module.css +18 -0
  9. package/ColorPicker/components/CustomColorModal/index.d.ts +15 -0
  10. package/ColorPicker/components/CustomColorModal/index.js +107 -0
  11. package/ColorPicker/components/HueSlider/HueSlider.module.css +31 -0
  12. package/ColorPicker/components/HueSlider/index.d.ts +10 -0
  13. package/ColorPicker/components/HueSlider/index.js +73 -0
  14. package/ColorPicker/components/Palette/Palette.module.css +12 -0
  15. package/ColorPicker/components/Palette/index.d.ts +19 -0
  16. package/ColorPicker/components/Palette/index.js +99 -0
  17. package/ColorPicker/components/SaturationPanel/SaturationPanel.module.css +26 -0
  18. package/ColorPicker/components/SaturationPanel/index.d.ts +13 -0
  19. package/ColorPicker/components/SaturationPanel/index.js +86 -0
  20. package/ColorPicker/components/Swatch/Swatch.module.css +36 -0
  21. package/ColorPicker/components/Swatch/index.d.ts +14 -0
  22. package/ColorPicker/components/Swatch/index.js +47 -0
  23. package/ColorPicker/hooks/useEyeDropper.d.ts +8 -0
  24. package/ColorPicker/hooks/useEyeDropper.js +38 -0
  25. package/ColorPicker/hooks/useHexDraft.d.ts +19 -0
  26. package/ColorPicker/hooks/useHexDraft.js +49 -0
  27. package/ColorPicker/hooks/usePointerDrag.d.ts +20 -0
  28. package/ColorPicker/hooks/usePointerDrag.js +55 -0
  29. package/ColorPicker/index.d.ts +3 -0
  30. package/ColorPicker/index.js +9 -0
  31. package/ColorPicker/index.props.d.ts +43 -0
  32. package/ColorPicker/package.json +9 -0
  33. package/ColorPicker/presets.d.ts +3 -0
  34. package/ColorPicker/presets.js +92 -0
  35. package/ColorPicker/utils/color.d.ts +25 -0
  36. package/ColorPicker/utils/color.js +162 -0
  37. package/Icons/Pipette.d.ts +3 -0
  38. package/Icons/Pipette.js +35 -0
  39. package/Icons/index.d.ts +1 -0
  40. package/Icons/index.js +2 -0
  41. package/NavigationMenu/NavigationMenu.d.ts +3 -0
  42. package/NavigationMenu/NavigationMenu.js +170 -0
  43. package/NavigationMenu/NavigationMenu.module.css +67 -0
  44. package/NavigationMenu/components/MoreMenu/MoreMenu.module.css +19 -0
  45. package/NavigationMenu/components/MoreMenu/index.d.ts +16 -0
  46. package/NavigationMenu/components/MoreMenu/index.js +155 -0
  47. package/NavigationMenu/components/NavigationLink/NavigationLink.module.css +59 -0
  48. package/NavigationMenu/components/NavigationLink/index.d.ts +16 -0
  49. package/NavigationMenu/components/NavigationLink/index.js +51 -0
  50. package/NavigationMenu/helpers.d.ts +9 -0
  51. package/NavigationMenu/helpers.js +20 -0
  52. package/NavigationMenu/index.d.ts +2 -0
  53. package/NavigationMenu/index.js +7 -0
  54. package/NavigationMenu/index.props.d.ts +40 -0
  55. package/NavigationMenu/package.json +9 -0
  56. package/NavigationMenu/splitItems.d.ts +30 -0
  57. package/NavigationMenu/splitItems.js +54 -0
  58. package/NavigationMenu/useOverflowSplit.d.ts +25 -0
  59. package/NavigationMenu/useOverflowSplit.js +63 -0
  60. package/Theme/index.d.ts +8 -0
  61. package/Theme/themes/buenos_aires.d.ts +4 -0
  62. package/Theme/themes/buenos_aires.js +4 -0
  63. package/Theme/themes/jaipur.d.ts +4 -0
  64. package/Theme/themes/jaipur.js +4 -0
  65. package/esm/ColorPicker/ColorPicker.d.ts +3 -0
  66. package/esm/ColorPicker/ColorPicker.js +108 -0
  67. package/esm/ColorPicker/ColorPicker.module.css +22 -0
  68. package/esm/ColorPicker/assets/none.png +0 -0
  69. package/esm/ColorPicker/components/ColorPreview/ColorPreview.module.css +23 -0
  70. package/esm/ColorPicker/components/ColorPreview/index.d.ts +10 -0
  71. package/esm/ColorPicker/components/ColorPreview/index.js +21 -0
  72. package/esm/ColorPicker/components/CustomColorModal/CustomColorModal.module.css +18 -0
  73. package/esm/ColorPicker/components/CustomColorModal/index.d.ts +15 -0
  74. package/esm/ColorPicker/components/CustomColorModal/index.js +100 -0
  75. package/esm/ColorPicker/components/HueSlider/HueSlider.module.css +31 -0
  76. package/esm/ColorPicker/components/HueSlider/index.d.ts +10 -0
  77. package/esm/ColorPicker/components/HueSlider/index.js +66 -0
  78. package/esm/ColorPicker/components/Palette/Palette.module.css +12 -0
  79. package/esm/ColorPicker/components/Palette/index.d.ts +19 -0
  80. package/esm/ColorPicker/components/Palette/index.js +92 -0
  81. package/esm/ColorPicker/components/SaturationPanel/SaturationPanel.module.css +26 -0
  82. package/esm/ColorPicker/components/SaturationPanel/index.d.ts +13 -0
  83. package/esm/ColorPicker/components/SaturationPanel/index.js +79 -0
  84. package/esm/ColorPicker/components/Swatch/Swatch.module.css +36 -0
  85. package/esm/ColorPicker/components/Swatch/index.d.ts +14 -0
  86. package/esm/ColorPicker/components/Swatch/index.js +38 -0
  87. package/esm/ColorPicker/hooks/useEyeDropper.d.ts +8 -0
  88. package/esm/ColorPicker/hooks/useEyeDropper.js +36 -0
  89. package/esm/ColorPicker/hooks/useHexDraft.d.ts +19 -0
  90. package/esm/ColorPicker/hooks/useHexDraft.js +47 -0
  91. package/esm/ColorPicker/hooks/usePointerDrag.d.ts +20 -0
  92. package/esm/ColorPicker/hooks/usePointerDrag.js +53 -0
  93. package/esm/ColorPicker/index.d.ts +3 -0
  94. package/esm/ColorPicker/index.js +2 -0
  95. package/esm/ColorPicker/index.props.d.ts +43 -0
  96. package/esm/ColorPicker/presets.d.ts +3 -0
  97. package/esm/ColorPicker/presets.js +89 -0
  98. package/esm/ColorPicker/utils/color.d.ts +25 -0
  99. package/esm/ColorPicker/utils/color.js +152 -0
  100. package/esm/Icons/Pipette.d.ts +3 -0
  101. package/esm/Icons/Pipette.js +29 -0
  102. package/esm/Icons/index.d.ts +1 -0
  103. package/esm/Icons/index.js +1 -0
  104. package/esm/NavigationMenu/NavigationMenu.d.ts +3 -0
  105. package/esm/NavigationMenu/NavigationMenu.js +162 -0
  106. package/esm/NavigationMenu/NavigationMenu.module.css +67 -0
  107. package/esm/NavigationMenu/components/MoreMenu/MoreMenu.module.css +19 -0
  108. package/esm/NavigationMenu/components/MoreMenu/index.d.ts +16 -0
  109. package/esm/NavigationMenu/components/MoreMenu/index.js +147 -0
  110. package/esm/NavigationMenu/components/NavigationLink/NavigationLink.module.css +59 -0
  111. package/esm/NavigationMenu/components/NavigationLink/index.d.ts +16 -0
  112. package/esm/NavigationMenu/components/NavigationLink/index.js +41 -0
  113. package/esm/NavigationMenu/helpers.d.ts +9 -0
  114. package/esm/NavigationMenu/helpers.js +15 -0
  115. package/esm/NavigationMenu/index.d.ts +2 -0
  116. package/esm/NavigationMenu/index.js +1 -0
  117. package/esm/NavigationMenu/index.props.d.ts +40 -0
  118. package/esm/NavigationMenu/splitItems.d.ts +30 -0
  119. package/esm/NavigationMenu/splitItems.js +51 -0
  120. package/esm/NavigationMenu/useOverflowSplit.d.ts +25 -0
  121. package/esm/NavigationMenu/useOverflowSplit.js +61 -0
  122. package/esm/Theme/index.d.ts +8 -0
  123. package/esm/Theme/themes/buenos_aires.d.ts +4 -0
  124. package/esm/Theme/themes/buenos_aires.js +4 -0
  125. package/esm/Theme/themes/jaipur.d.ts +4 -0
  126. package/esm/Theme/themes/jaipur.js +4 -0
  127. package/esm/index.d.ts +4 -0
  128. package/esm/index.js +4 -0
  129. package/esm/theme_ba_variables.css +4 -0
  130. package/esm/theme_jaipur_variables.css +4 -0
  131. package/index.d.ts +4 -0
  132. package/index.js +10 -0
  133. package/package.json +1 -1
  134. package/theme_ba_variables.css +4 -0
  135. package/theme_jaipur_variables.css +4 -0
@@ -0,0 +1,59 @@
1
+ .item {
2
+ align-items: center;
3
+ background: transparent;
4
+ block-size: var(--navigation-item-height);
5
+ border: none;
6
+ border-radius: var(--radius-full);
7
+ box-sizing: border-box;
8
+ color: var(--component-navigation-item-text);
9
+ cursor: pointer;
10
+ display: inline-flex;
11
+ font: inherit;
12
+ font-size: var(--navigation-item-font-size);
13
+ gap: var(--space-2);
14
+ line-height: var(--navigation-item-line-height);
15
+ padding: 0 var(--navigation-item-padding);
16
+ text-decoration: none;
17
+ transition: background-color 0.15s ease;
18
+ white-space: nowrap;
19
+ }
20
+ .item:hover {
21
+ background: var(--component-navigation-item-bg-hover);
22
+ }
23
+ .item:focus-visible {
24
+ outline: var(--focus-ring-width) solid var(--component-navigation-item-focus-ring);
25
+ outline-offset: calc(var(--focus-ring-width) * -1);
26
+ }
27
+ .item_selected, .item_selected:hover {
28
+ background: var(--component-navigation-item-bg-selected);
29
+ color: var(--component-navigation-item-text-selected);
30
+ }
31
+
32
+ .option {
33
+ align-items: center;
34
+ border-radius: var(--radius-xs);
35
+ color: var(--component-menu-text);
36
+ display: flex;
37
+ font-size: var(--font-size-text-sm);
38
+ gap: var(--space-2);
39
+ line-height: var(--line-height-text-sm);
40
+ outline: none;
41
+ padding: var(--space-2) var(--space-3);
42
+ text-decoration: none;
43
+ }
44
+ .option:hover, .option:focus-visible {
45
+ background: var(--component-menu-item-bg-hover);
46
+ }
47
+ .option_selected, .option_selected:hover, .option_selected:focus-visible {
48
+ background: var(--component-navigation-item-bg-selected);
49
+ color: var(--component-navigation-item-text-selected);
50
+ }
51
+ .option_selected:focus-visible {
52
+ outline: var(--focus-ring-width) solid var(--component-navigation-item-focus-ring);
53
+ outline-offset: calc(var(--focus-ring-width) * -1);
54
+ }
55
+
56
+ .icon {
57
+ display: inline-flex;
58
+ flex-shrink: 0;
59
+ }
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import type { NavigationMenuItem, NavigationMenuRenderLink } from "../../index.props";
3
+ interface NavigationLinkProps {
4
+ item: NavigationMenuItem;
5
+ /** `item` is a pill in the row, `option` is a line inside "More". */
6
+ view?: "item" | "option";
7
+ role?: "menuitem";
8
+ onClick?: (item: NavigationMenuItem) => void;
9
+ renderLink?: NavigationMenuRenderLink;
10
+ }
11
+ export declare const getLinkClassName: (view?: NavigationLinkProps["view"], active?: boolean) => string;
12
+ export declare const LinkContent: ({ item }: {
13
+ item: NavigationMenuItem;
14
+ }) => React.JSX.Element;
15
+ export declare const NavigationLink: ({ item, view, role, onClick, renderLink, }: NavigationLinkProps) => React.JSX.Element;
16
+ export {};
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var clsx = require('clsx');
5
+ var styles = require('./NavigationLink.module.css');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefault(React);
10
+ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
11
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
12
+
13
+ const getLinkClassName = (view = "item", active) => clsx__default.default(styles__default.default[view], {
14
+ [styles__default.default[`${view}_selected`]]: active
15
+ });
16
+ const LinkContent = ({
17
+ item
18
+ }) => (/*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null, item.icon && (/*#__PURE__*/React__default.default.createElement("span", {
19
+ className: styles__default.default.icon,
20
+ "aria-hidden": "true"
21
+ }, item.icon)), /*#__PURE__*/React__default.default.createElement("span", null, item.label)));
22
+ const NavigationLink = ({
23
+ item,
24
+ view,
25
+ role,
26
+ onClick,
27
+ renderLink
28
+ }) => {
29
+ const props = {
30
+ item,
31
+ className: getLinkClassName(view, item.active),
32
+ children: /*#__PURE__*/React__default.default.createElement(LinkContent, {
33
+ item: item
34
+ }),
35
+ onClick: onClick ? () => onClick(item) : undefined,
36
+ role,
37
+ "aria-current": item.active ? "page" : undefined
38
+ };
39
+ if (renderLink) return /*#__PURE__*/React__default.default.createElement(React__default.default.Fragment, null, renderLink(props));
40
+ return /*#__PURE__*/React__default.default.createElement("a", {
41
+ href: item.href,
42
+ className: props.className,
43
+ onClick: props.onClick,
44
+ role: role,
45
+ "aria-current": props["aria-current"]
46
+ }, props.children);
47
+ };
48
+
49
+ exports.LinkContent = LinkContent;
50
+ exports.NavigationLink = NavigationLink;
51
+ exports.getLinkClassName = getLinkClassName;
@@ -0,0 +1,9 @@
1
+ import { useLayoutEffect } from "react";
2
+ import type { Ref } from "react";
3
+ import type { NavigationMenuItem } from "./index.props";
4
+ export declare const getItemKey: (item: NavigationMenuItem, index: number) => string;
5
+ /** Items are often recreated on every render: compare them by content. */
6
+ export declare const isSameItem: (a: NavigationMenuItem, b: NavigationMenuItem) => boolean;
7
+ /** `useLayoutEffect` without the server rendering warning. */
8
+ export declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
9
+ export declare const assignRef: <T>(ref: Ref<T> | undefined, value: T | null) => void;
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ const getItemKey = (item, index) => {
6
+ var _a, _b;
7
+ return (_b = (_a = item.id) !== null && _a !== void 0 ? _a : item.href) !== null && _b !== void 0 ? _b : `${item.label}-${index}`;
8
+ };
9
+ /** Items are often recreated on every render: compare them by content. */
10
+ const isSameItem = (a, b) => getItemKey(a, 0) === getItemKey(b, 0);
11
+ /** `useLayoutEffect` without the server rendering warning. */
12
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
13
+ const assignRef = (ref, value) => {
14
+ if (typeof ref === "function") ref(value);else if (ref) ref.current = value;
15
+ };
16
+
17
+ exports.assignRef = assignRef;
18
+ exports.getItemKey = getItemKey;
19
+ exports.isSameItem = isSameItem;
20
+ exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
@@ -0,0 +1,2 @@
1
+ export { NavigationMenu } from "./NavigationMenu";
2
+ export type { NavigationMenuItem, NavigationMenuLayout, NavigationMenuLinkProps, NavigationMenuProps, NavigationMenuRenderLink, NavigationMenuSize, } from "./index.props";
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ var NavigationMenu = require('./NavigationMenu.js');
4
+
5
+
6
+
7
+ exports.NavigationMenu = NavigationMenu.NavigationMenu;
@@ -0,0 +1,40 @@
1
+ import type { HTMLAttributes, MouseEventHandler, ReactNode } from "react";
2
+ /** `overflow` keeps items in a row and moves the rest to "More", `scroll` is a horizontal strip. */
3
+ export type NavigationMenuLayout = "overflow" | "scroll";
4
+ export type NavigationMenuSize = "s" | "m";
5
+ export interface NavigationMenuItem {
6
+ /** Unique key. Defaults to `href`, then to `label`. */
7
+ id?: string;
8
+ label: string;
9
+ href?: string;
10
+ /** Current section: highlighted, gets `aria-current="page"` and never moves to "More". */
11
+ active?: boolean;
12
+ /** Icon before the label. */
13
+ icon?: ReactNode;
14
+ }
15
+ export interface NavigationMenuLinkProps {
16
+ item: NavigationMenuItem;
17
+ className: string;
18
+ children: ReactNode;
19
+ onClick?: MouseEventHandler<HTMLElement>;
20
+ tabIndex?: number;
21
+ /** Set for links inside the "More" dropdown. */
22
+ role?: "menuitem";
23
+ "aria-current"?: "page";
24
+ }
25
+ /** Renders an item link, for example a router `Link`. Pass every prop except `item` to the element. */
26
+ export type NavigationMenuRenderLink = (props: NavigationMenuLinkProps) => ReactNode;
27
+ export interface NavigationMenuProps extends Omit<HTMLAttributes<HTMLElement>, "children"> {
28
+ items: NavigationMenuItem[];
29
+ /** Always visible after `items`. */
30
+ pinnedItems?: NavigationMenuItem[];
31
+ /** Always inside "More", after the items that do not fit. In the `scroll` layout they end the strip. */
32
+ moreItems?: NavigationMenuItem[];
33
+ layout?: NavigationMenuLayout;
34
+ size?: NavigationMenuSize;
35
+ moreLabel?: ReactNode;
36
+ /** Called on a click on any item, including the ones inside "More". */
37
+ onItemClick?: (item: NavigationMenuItem) => void;
38
+ /** Custom link. Defaults to `<a href>`. */
39
+ renderLink?: NavigationMenuRenderLink;
40
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "sideEffects": [
3
+ "**/*.css",
4
+ "**/*.scss"
5
+ ],
6
+ "module": "../esm/NavigationMenu/index.js",
7
+ "main": "./index.js",
8
+ "types": "./index.d.ts"
9
+ }
@@ -0,0 +1,30 @@
1
+ export interface SplitInput {
2
+ itemWidths: number[];
3
+ /** Pinned items are always visible and go after the main items. */
4
+ pinnedWidths: number[];
5
+ moreWidth: number;
6
+ containerWidth: number;
7
+ /** CSS gap between items. */
8
+ gap: number;
9
+ /** Index of the active item or -1. */
10
+ activeIndex: number;
11
+ /** "More" is needed anyway, for example for `moreItems`. */
12
+ forceMore: boolean;
13
+ }
14
+ export interface SplitResult {
15
+ /** Indexes of the items left in the row, in the original order. */
16
+ visible: number[];
17
+ /** Indexes of the items moved to "More", in the original order. */
18
+ hidden: number[];
19
+ }
20
+ /**
21
+ * Splits items into the row and "More".
22
+ *
23
+ * Items go from left to right while they fit; the first one that does not fit
24
+ * and all after it move to "More". Space for the active item is reserved
25
+ * first, so it stays in the row and its neighbours move instead. Every element
26
+ * costs its width plus gap; the budget has one extra gap because N elements
27
+ * have N − 1 gaps.
28
+ */
29
+ export declare const splitItems: ({ itemWidths, pinnedWidths, moreWidth, containerWidth, gap, activeIndex, forceMore, }: SplitInput) => SplitResult;
30
+ export declare const isSameSplit: (a: SplitResult, b: SplitResult) => boolean;
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const sum = list => list.reduce((acc, n) => acc + n, 0);
4
+ /**
5
+ * Splits items into the row and "More".
6
+ *
7
+ * Items go from left to right while they fit; the first one that does not fit
8
+ * and all after it move to "More". Space for the active item is reserved
9
+ * first, so it stays in the row and its neighbours move instead. Every element
10
+ * costs its width plus gap; the budget has one extra gap because N elements
11
+ * have N − 1 gaps.
12
+ */
13
+ const splitItems = ({
14
+ itemWidths,
15
+ pinnedWidths,
16
+ moreWidth,
17
+ containerWidth,
18
+ gap,
19
+ activeIndex,
20
+ forceMore
21
+ }) => {
22
+ const all = itemWidths.map((_, index) => index);
23
+ const cost = width => width + gap;
24
+ const pinnedCost = sum(pinnedWidths.map(cost));
25
+ if (!forceMore && sum(itemWidths.map(cost)) + pinnedCost <= containerWidth + gap) {
26
+ return {
27
+ visible: all,
28
+ hidden: []
29
+ };
30
+ }
31
+ const hasActive = activeIndex >= 0 && activeIndex < itemWidths.length;
32
+ let budget = containerWidth + gap - pinnedCost - cost(moreWidth);
33
+ if (hasActive) budget -= cost(itemWidths[activeIndex]);
34
+ const visible = [];
35
+ for (let index = 0; index < itemWidths.length; index++) {
36
+ if (index === activeIndex) continue;
37
+ if (cost(itemWidths[index]) > budget) break;
38
+ budget -= cost(itemWidths[index]);
39
+ visible.push(index);
40
+ }
41
+ if (hasActive) {
42
+ visible.push(activeIndex);
43
+ visible.sort((a, b) => a - b);
44
+ }
45
+ return {
46
+ visible,
47
+ hidden: all.filter(index => !visible.includes(index))
48
+ };
49
+ };
50
+ const isSameList = (a, b) => a.length === b.length && a.every((index, position) => index === b[position]);
51
+ const isSameSplit = (a, b) => isSameList(a.visible, b.visible) && isSameList(a.hidden, b.hidden);
52
+
53
+ exports.isSameSplit = isSameSplit;
54
+ exports.splitItems = splitItems;
@@ -0,0 +1,25 @@
1
+ import type { SplitResult } from "./splitItems";
2
+ interface Options {
3
+ itemCount: number;
4
+ pinnedCount: number;
5
+ activeIndex: number;
6
+ forceMore: boolean;
7
+ /** Changes with the item labels to recalculate. */
8
+ contentKey: string;
9
+ }
10
+ /**
11
+ * Measures the items and splits them into the row and "More".
12
+ *
13
+ * Widths come from a hidden measurer that always renders every item, so the
14
+ * items inside "More" are measured too, for example after a web font loads.
15
+ * ResizeObserver watches the container, the measurer and the "More" trigger.
16
+ * Before the first measurement, and on the server, `split` is `null`.
17
+ */
18
+ export declare const useOverflowSplit: ({ itemCount, pinnedCount, activeIndex, forceMore, contentKey, }: Options) => {
19
+ split: SplitResult | null;
20
+ containerRef: import("react").RefObject<HTMLElement | null>;
21
+ listRef: import("react").RefObject<HTMLUListElement | null>;
22
+ measurerRef: import("react").RefObject<HTMLDivElement | null>;
23
+ moreRef: import("react").RefObject<HTMLLIElement | null>;
24
+ };
25
+ export {};
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var helpers = require('./helpers.js');
5
+ var splitItems = require('./splitItems.js');
6
+
7
+ const getWidth = element => element ? element.getBoundingClientRect().width : 0;
8
+ /**
9
+ * Measures the items and splits them into the row and "More".
10
+ *
11
+ * Widths come from a hidden measurer that always renders every item, so the
12
+ * items inside "More" are measured too, for example after a web font loads.
13
+ * ResizeObserver watches the container, the measurer and the "More" trigger.
14
+ * Before the first measurement, and on the server, `split` is `null`.
15
+ */
16
+ const useOverflowSplit = ({
17
+ itemCount,
18
+ pinnedCount,
19
+ activeIndex,
20
+ forceMore,
21
+ contentKey
22
+ }) => {
23
+ const containerRef = React.useRef(null);
24
+ const listRef = React.useRef(null);
25
+ const measurerRef = React.useRef(null);
26
+ const moreRef = React.useRef(null);
27
+ const [split, setSplit] = React.useState(null);
28
+ helpers.useIsomorphicLayoutEffect(() => {
29
+ const container = containerRef.current;
30
+ const measurer = measurerRef.current;
31
+ if (!container || !measurer) return undefined;
32
+ const recalculate = () => {
33
+ const widths = Array.from(measurer.children, getWidth);
34
+ const gap = listRef.current ? parseFloat(getComputedStyle(listRef.current).columnGap) || 0 : 0;
35
+ const next = splitItems.splitItems({
36
+ itemWidths: widths.slice(0, itemCount),
37
+ pinnedWidths: widths.slice(itemCount, itemCount + pinnedCount),
38
+ moreWidth: getWidth(moreRef.current),
39
+ containerWidth: getWidth(container),
40
+ gap,
41
+ activeIndex,
42
+ forceMore
43
+ });
44
+ setSplit(prev => prev && splitItems.isSameSplit(prev, next) ? prev : next);
45
+ };
46
+ recalculate();
47
+ if (typeof ResizeObserver === "undefined") return undefined;
48
+ const observer = new ResizeObserver(recalculate);
49
+ observer.observe(container);
50
+ observer.observe(measurer);
51
+ if (moreRef.current) observer.observe(moreRef.current);
52
+ return () => observer.disconnect();
53
+ }, [itemCount, pinnedCount, activeIndex, forceMore, contentKey]);
54
+ return {
55
+ split,
56
+ containerRef,
57
+ listRef,
58
+ measurerRef,
59
+ moreRef
60
+ };
61
+ };
62
+
63
+ exports.useOverflowSplit = useOverflowSplit;
package/Theme/index.d.ts CHANGED
@@ -692,7 +692,11 @@ export declare const THEMES: {
692
692
  "component-pagination-bg-current": string;
693
693
  "component-pagination-bg-hover": string;
694
694
  "component-pagination-focus-ring": string;
695
+ "component-navigation-item-text": string;
696
+ "component-navigation-item-text-selected": string;
697
+ "component-navigation-item-bg-hover": string;
695
698
  "component-navigation-item-bg-selected": string;
699
+ "component-navigation-item-focus-ring": string;
696
700
  "component-chip-bg-selected": string;
697
701
  "component-chip-bg-selected-strong": string;
698
702
  "palette-black": string;
@@ -1536,7 +1540,11 @@ export declare const THEMES: {
1536
1540
  "component-pagination-bg-current": string;
1537
1541
  "component-pagination-bg-hover": string;
1538
1542
  "component-pagination-focus-ring": string;
1543
+ "component-navigation-item-text": string;
1544
+ "component-navigation-item-text-selected": string;
1545
+ "component-navigation-item-bg-hover": string;
1539
1546
  "component-navigation-item-bg-selected": string;
1547
+ "component-navigation-item-focus-ring": string;
1540
1548
  "component-chip-bg-selected": string;
1541
1549
  "component-chip-bg-selected-strong": string;
1542
1550
  "palette-black": string;
@@ -613,7 +613,11 @@ declare const _default: {
613
613
  "component-pagination-bg-current": string;
614
614
  "component-pagination-bg-hover": string;
615
615
  "component-pagination-focus-ring": string;
616
+ "component-navigation-item-text": string;
617
+ "component-navigation-item-text-selected": string;
618
+ "component-navigation-item-bg-hover": string;
616
619
  "component-navigation-item-bg-selected": string;
620
+ "component-navigation-item-focus-ring": string;
617
621
  "component-chip-bg-selected": string;
618
622
  "component-chip-bg-selected-strong": string;
619
623
  "palette-black": string;
@@ -619,7 +619,11 @@ var THEME_BA = {
619
619
  "component-pagination-bg-current": theme_buenos_aires.default.BRAND_BA_FOREST,
620
620
  "component-pagination-bg-hover": theme_buenos_aires.default.NEUTRAL_BA_100,
621
621
  "component-pagination-focus-ring": theme_buenos_aires.default.BRAND_BA_LIME,
622
+ "component-navigation-item-text": theme_buenos_aires.default.BRAND_BA_FOREST,
623
+ "component-navigation-item-text-selected": theme_buenos_aires.default.BRAND_BA_LIME,
624
+ "component-navigation-item-bg-hover": theme_buenos_aires.default.NEUTRAL_BA_100,
622
625
  "component-navigation-item-bg-selected": theme_buenos_aires.default.BRAND_BA_FOREST,
626
+ "component-navigation-item-focus-ring": theme_buenos_aires.default.BRAND_BA_LIME,
623
627
  "component-chip-bg-selected": theme_buenos_aires.default.BRAND_BA_FOREST,
624
628
  "component-chip-bg-selected-strong": theme_buenos_aires.default.BRAND_BA_LIME,
625
629
  "palette-black": theme_buenos_aires.default.BRAND_BA_FOREST,
@@ -613,7 +613,11 @@ declare const _default: {
613
613
  "component-pagination-bg-current": string;
614
614
  "component-pagination-bg-hover": string;
615
615
  "component-pagination-focus-ring": string;
616
+ "component-navigation-item-text": string;
617
+ "component-navigation-item-text-selected": string;
618
+ "component-navigation-item-bg-hover": string;
616
619
  "component-navigation-item-bg-selected": string;
620
+ "component-navigation-item-focus-ring": string;
617
621
  "component-chip-bg-selected": string;
618
622
  "component-chip-bg-selected-strong": string;
619
623
  "palette-black": string;
@@ -619,7 +619,11 @@ var theme_jaipur = {
619
619
  "component-pagination-bg-current": theme_jaipur$1.default.BRAND_JP_EGGPLANT,
620
620
  "component-pagination-bg-hover": theme_jaipur$1.default.NEUTRAL_JP_100,
621
621
  "component-pagination-focus-ring": theme_jaipur$1.default.BRAND_JP_PINK,
622
+ "component-navigation-item-text": theme_jaipur$1.default.BRAND_JP_EGGPLANT,
623
+ "component-navigation-item-text-selected": theme_jaipur$1.default.BRAND_JP_PINK,
624
+ "component-navigation-item-bg-hover": theme_jaipur$1.default.NEUTRAL_JP_100,
622
625
  "component-navigation-item-bg-selected": theme_jaipur$1.default.BRAND_JP_EGGPLANT,
626
+ "component-navigation-item-focus-ring": theme_jaipur$1.default.BRAND_JP_PINK,
623
627
  "component-chip-bg-selected": theme_jaipur$1.default.BRAND_JP_EGGPLANT,
624
628
  "component-chip-bg-selected-strong": theme_jaipur$1.default.BRAND_JP_PINK,
625
629
  "palette-black": theme_jaipur$1.default.BRAND_JP_EGGPLANT,
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { ColorPickerProps } from "./index.props";
3
+ export declare const ColorPicker: ({ value, onChange, presets, columns, disabled, placement, zIndex, labels: labelsProp, children, }: ColorPickerProps) => React.JSX.Element;
@@ -0,0 +1,108 @@
1
+ import React, { useState, useRef, useMemo } from 'react';
2
+ import clsx from 'clsx';
3
+ import { Button } from '../Button/index.js';
4
+ import { Dropdown } from '../Dropdown/index.js';
5
+ import { CustomColorModal } from './components/CustomColorModal/index.js';
6
+ import { Palette } from './components/Palette/index.js';
7
+ import { DEFAULT_LABELS, COLOR_PICKER_PRESETS } from './presets.js';
8
+ import { normalizeHex } from './utils/color.js';
9
+ import styles from './ColorPicker.module.css';
10
+
11
+ const normalizePresets = presets => presets.flatMap(preset => {
12
+ const value = normalizeHex(preset.value);
13
+ return value ? [Object.assign(Object.assign({}, preset), {
14
+ value
15
+ })] : [];
16
+ });
17
+ const ColorPicker = ({
18
+ value,
19
+ onChange,
20
+ presets = COLOR_PICKER_PRESETS,
21
+ columns = 6,
22
+ disabled,
23
+ placement = "bottom-start",
24
+ zIndex,
25
+ labels: labelsProp,
26
+ children
27
+ }) => {
28
+ var _a, _b;
29
+ const [isOpen, setOpen] = useState(false);
30
+ const [isCustomOpen, setCustomOpen] = useState(false);
31
+ const rootRef = useRef(null);
32
+ const overlayRef = useRef(null);
33
+ const labels = Object.assign(Object.assign({}, DEFAULT_LABELS), labelsProp);
34
+ const current = value ? normalizeHex(value) : null;
35
+ const normalizedPresets = useMemo(() => normalizePresets(presets), [presets]);
36
+ // Selection, "+" and Escape remove the focused swatch together with the
37
+ // dropdown: return focus to the trigger. The custom color dialog then
38
+ // restores focus to the trigger as well.
39
+ const closeDropdown = () => {
40
+ var _a, _b;
41
+ const trigger = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.firstElementChild;
42
+ if (((_b = overlayRef.current) === null || _b === void 0 ? void 0 : _b.contains(document.activeElement)) && trigger instanceof HTMLElement) {
43
+ trigger.focus();
44
+ }
45
+ setOpen(false);
46
+ };
47
+ const handleVisibleChange = visible => {
48
+ if (visible) setOpen(true);else closeDropdown();
49
+ };
50
+ const handleSelect = hex => {
51
+ closeDropdown();
52
+ onChange(hex);
53
+ };
54
+ const handleAddClick = () => {
55
+ closeDropdown();
56
+ setCustomOpen(true);
57
+ };
58
+ const handleSave = hex => {
59
+ setCustomOpen(false);
60
+ onChange(hex);
61
+ };
62
+ const trigger = children !== null && children !== void 0 ? children : (/*#__PURE__*/React.createElement(Button, {
63
+ variant: "outline",
64
+ className: clsx({
65
+ [styles.trigger_empty]: !current
66
+ }),
67
+ disabled: disabled,
68
+ "aria-label": labels.trigger,
69
+ icon: /*#__PURE__*/React.createElement("span", {
70
+ className: clsx(styles.dot, {
71
+ [styles.dot_hidden]: !current
72
+ }),
73
+ style: current ? {
74
+ backgroundColor: current
75
+ } : undefined
76
+ })
77
+ }));
78
+ return /*#__PURE__*/React.createElement("span", {
79
+ ref: rootRef,
80
+ className: styles.root
81
+ }, /*#__PURE__*/React.createElement(Dropdown, {
82
+ trigger: ["click"],
83
+ visible: isOpen,
84
+ onVisibleChange: handleVisibleChange,
85
+ preventAutoClose: true,
86
+ disabled: disabled,
87
+ placement: placement,
88
+ zIndex: zIndex,
89
+ overlay: /*#__PURE__*/React.createElement("div", {
90
+ ref: overlayRef
91
+ }, /*#__PURE__*/React.createElement(Palette, {
92
+ presets: normalizedPresets,
93
+ value: current,
94
+ columns: columns,
95
+ labels: labels,
96
+ onSelect: handleSelect,
97
+ onAddClick: handleAddClick,
98
+ onTabOut: closeDropdown
99
+ }))
100
+ }, trigger), isCustomOpen && (/*#__PURE__*/React.createElement(CustomColorModal, {
101
+ initialColor: (_b = current !== null && current !== void 0 ? current : (_a = normalizedPresets[0]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "#000000",
102
+ labels: labels,
103
+ onSave: handleSave,
104
+ onClose: () => setCustomOpen(false)
105
+ })));
106
+ };
107
+
108
+ export { ColorPicker };
@@ -0,0 +1,22 @@
1
+ .root {
2
+ display: contents;
3
+ }
4
+
5
+ .dot {
6
+ border-radius: var(--radius-full);
7
+ box-shadow: inset 0 0 0 var(--border-width-hairline) var(--color-border-default);
8
+ display: block;
9
+ height: var(--space-4);
10
+ width: var(--space-4);
11
+ }
12
+
13
+ .trigger_empty {
14
+ background-image: url("./assets/none.png");
15
+ background-position: center;
16
+ background-repeat: no-repeat;
17
+ background-size: cover;
18
+ }
19
+
20
+ .dot_hidden {
21
+ display: none;
22
+ }
Binary file
@@ -0,0 +1,23 @@
1
+ .root {
2
+ align-items: center;
3
+ border-radius: var(--radius-full);
4
+ box-shadow: inset 0 0 0 var(--border-width-hairline) var(--color-border-subtle);
5
+ display: inline-flex;
6
+ flex-shrink: 0;
7
+ font-family: var(--font-family-ui);
8
+ font-size: var(--font-size-heading-md);
9
+ font-weight: var(--font-weight-medium);
10
+ height: var(--space-12);
11
+ justify-content: center;
12
+ line-height: 1;
13
+ transition: background-color 0.1s ease, color 0.1s ease;
14
+ width: var(--space-12);
15
+ }
16
+
17
+ .text_light {
18
+ color: var(--color-neutral-0);
19
+ }
20
+
21
+ .text_dark {
22
+ color: var(--color-neutral-950);
23
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { ReactNode } from "react";
3
+ import type { HSV } from "../../utils/color";
4
+ interface ColorPreviewProps {
5
+ color: HSV;
6
+ children: ReactNode;
7
+ }
8
+ /** Circle with the color and a sample text in the automatically adjusted color. */
9
+ export declare const ColorPreview: ({ color, children }: ColorPreviewProps) => React.JSX.Element;
10
+ export {};