@clubmed/trident-ui 2.0.0-beta.2 → 2.0.0-beta.21

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 (87) hide show
  1. package/chunks/DateField.js +36 -35
  2. package/chunks/DateField.js.map +1 -1
  3. package/examples/button-demo.js +2 -2
  4. package/examples/button-demo.js.map +1 -1
  5. package/examples/checkbox-demo.js +16 -20
  6. package/examples/checkbox-demo.js.map +1 -1
  7. package/examples/checkboxes-demo.js +6 -6
  8. package/examples/checkboxes-demo.js.map +1 -1
  9. package/examples/choice-expander-demo.js +4 -67
  10. package/examples/choice-expander-demo.js.map +1 -1
  11. package/examples/dropdown-demo.js +9 -1
  12. package/examples/dropdown-demo.js.map +1 -1
  13. package/examples/elastic-height-demo.js +2 -1
  14. package/examples/elastic-height-demo.js.map +1 -1
  15. package/examples/frame-demo.d.ts +1 -0
  16. package/examples/frame-demo.js +18 -0
  17. package/examples/frame-demo.js.map +1 -0
  18. package/examples/frame-horizontal-demo.d.ts +1 -0
  19. package/examples/frame-horizontal-demo.js +18 -0
  20. package/examples/frame-horizontal-demo.js.map +1 -0
  21. package/examples/frame-vertical-demo.d.ts +1 -0
  22. package/examples/frame-vertical-demo.js +18 -0
  23. package/examples/frame-vertical-demo.js.map +1 -0
  24. package/examples/frame-with-tag-demo.d.ts +1 -0
  25. package/examples/frame-with-tag-demo.js +23 -0
  26. package/examples/frame-with-tag-demo.js.map +1 -0
  27. package/examples/sidebar-layout-demo.js +5 -5
  28. package/examples/sidebar-layout-demo.js.map +1 -1
  29. package/examples/sidebar-layout-minimal-demo.js +2 -2
  30. package/examples/sidebar-layout-minimal-demo.js.map +1 -1
  31. package/examples/sidebar-layout-with-header-demo.js +2 -2
  32. package/examples/sidebar-layout-with-header-demo.js.map +1 -1
  33. package/package.json +2 -1
  34. package/styles/animate.css +19 -19
  35. package/styles/theme.css +23 -18
  36. package/styles/ui/button.css +18 -24
  37. package/styles/ui/controls.css +1 -11
  38. package/styles/variants.css +0 -2
  39. package/ui/AdvancedToast.js +11 -11
  40. package/ui/AdvancedToast.js.map +1 -1
  41. package/ui/BasicToast.js +1 -1
  42. package/ui/BasicToast.js.map +1 -1
  43. package/ui/Breadcrumb.d.ts +2 -2
  44. package/ui/Breadcrumb.js +31 -35
  45. package/ui/Breadcrumb.js.map +1 -1
  46. package/ui/ChoiceExpander.js +1 -1
  47. package/ui/ChoiceExpander.js.map +1 -1
  48. package/ui/Dropdown.d.ts +20 -3
  49. package/ui/Dropdown.js +57 -23
  50. package/ui/Dropdown.js.map +1 -1
  51. package/ui/ElasticHeight.d.ts +0 -1
  52. package/ui/ElasticHeight.js +14 -23
  53. package/ui/ElasticHeight.js.map +1 -1
  54. package/ui/Frame.d.ts +15 -0
  55. package/ui/Frame.js +39 -0
  56. package/ui/Frame.js.map +1 -0
  57. package/ui/Loader.d.ts +5 -4
  58. package/ui/Loader.js +11 -10
  59. package/ui/Loader.js.map +1 -1
  60. package/ui/Popin.js +2 -2
  61. package/ui/Popin.js.map +1 -1
  62. package/ui/SidebarLayout.d.ts +11 -7
  63. package/ui/SidebarLayout.js +55 -34
  64. package/ui/SidebarLayout.js.map +1 -1
  65. package/ui/arrows/Arrows.d.ts +1 -0
  66. package/ui/arrows/Arrows.js +19 -17
  67. package/ui/arrows/Arrows.js.map +1 -1
  68. package/ui/buttons/Button.type.d.ts +1 -1
  69. package/ui/buttons/Button.type.js.map +1 -1
  70. package/ui/forms/Filter.d.ts +8 -4
  71. package/ui/forms/Filter.js +23 -45
  72. package/ui/forms/Filter.js.map +1 -1
  73. package/ui/forms/FormControl.js +6 -6
  74. package/ui/forms/NumberField.d.ts +10 -10
  75. package/ui/forms/checkboxes/Checkbox.d.ts +10 -12
  76. package/ui/forms/checkboxes/Checkbox.js +38 -55
  77. package/ui/forms/checkboxes/Checkbox.js.map +1 -1
  78. package/ui/forms/checkboxes/Checkboxes.js +2 -2
  79. package/ui/forms/checkboxes/Checkboxes.js.map +1 -1
  80. package/ui/helpers/colors/colors.d.ts +4 -0
  81. package/ui/helpers/colors/colors.js +6 -1
  82. package/ui/helpers/colors/colors.js.map +1 -1
  83. package/ui/hooks/useValue.js +1 -1
  84. package/ui/hooks/useValue.js.map +1 -1
  85. package/ui/Breadcrumb.themes.d.ts +0 -8
  86. package/ui/Breadcrumb.themes.js +0 -16
  87. package/ui/Breadcrumb.themes.js.map +0 -1
@@ -1,15 +1,15 @@
1
1
  "use client";
2
2
  import { t as e } from "../chunks/clsx.js";
3
- import t from "./hooks/useResizeObserver.js";
4
- import { ElasticHeight as n } from "./ElasticHeight.js";
5
- import { Colors as r, getBgColor as i, getBorderColor as a, getTextColor as o } from "./helpers/colors/colors.js";
6
- import { useCountdown as s } from "./hooks/useCountdown.js";
3
+ import { ElasticHeight as t } from "./ElasticHeight.js";
4
+ import { Colors as n, getBgColor as r, getBorderColor as i, getTextColor as a } from "./helpers/colors/colors.js";
5
+ import { useCountdown as o } from "./hooks/useCountdown.js";
6
+ import s from "./hooks/useResizeObserver.js";
7
7
  import { useEffect as c, useId as l, useRef as u, useState as d } from "react";
8
8
  import { Icon as f } from "@clubmed/trident-icons";
9
9
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
10
10
  //#region lib/ui/AdvancedToast.tsx
11
- var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, children: x, accentColor: S = r.orange, duration: C = 1e4, onClose: w, toastId: T, updateHeight: E, ...D }) => {
12
- let O = l(), [k, A] = d(!1), [j, M] = d(!1), N = u(null), { progress: P } = s({
11
+ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, children: x, accentColor: S = n.orange, duration: C = 1e4, onClose: w, toastId: T, updateHeight: E, ...D }) => {
12
+ let O = l(), [k, A] = d(!1), [j, M] = d(!1), N = u(null), { progress: P } = o({
13
13
  duration: C,
14
14
  isPaused: j,
15
15
  isVisible: y
@@ -18,7 +18,7 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
18
18
  P === 100 && w?.();
19
19
  }, [P, w]);
20
20
  let F = () => M(!0), I = () => M(!1), L = () => M(!1);
21
- return t({
21
+ return s({
22
22
  ref: N,
23
23
  onResize: () => {
24
24
  N.current && E(T, N.current.offsetHeight);
@@ -26,7 +26,7 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
26
26
  }), /* @__PURE__ */ m("div", {
27
27
  ref: N,
28
28
  ...D,
29
- className: e(y ? "animate-slideRightEnter" : "animate-slideRightExit opacity-0", "relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden", a(S), h),
29
+ className: e(y ? "animate-slide-right-enter" : "animate-slide-right-exit opacity-0", "relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden", i(S), h),
30
30
  role: "note",
31
31
  onMouseDown: F,
32
32
  onMouseUp: I,
@@ -35,7 +35,7 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
35
35
  /* @__PURE__ */ p(f, {
36
36
  name: v,
37
37
  width: "30px",
38
- className: e("flex-shrink-0 pt-4", o(S))
38
+ className: e("flex-shrink-0 pt-4", a(S))
39
39
  }),
40
40
  /* @__PURE__ */ m("div", {
41
41
  className: "flex flex-1 flex-col gap-12 pe-24 text-b4",
@@ -54,7 +54,7 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
54
54
  style: { rotate: k ? "180deg" : "0deg" },
55
55
  className: "transition-all duration-300"
56
56
  })]
57
- }), /* @__PURE__ */ p(n, {
57
+ }), /* @__PURE__ */ p(t, {
58
58
  isExpanded: k,
59
59
  children: /* @__PURE__ */ p("div", {
60
60
  className: "pt-4",
@@ -76,7 +76,7 @@ var h = ({ className: h, title: g, body: _, icon: v, isVisible: y, labels: b, ch
76
76
  C !== !1 && /* @__PURE__ */ p("div", {
77
77
  className: "absolute bottom-0 left-0 right-0 h-4 overflow-hidden rounded-b-16",
78
78
  children: /* @__PURE__ */ p("div", {
79
- className: i(S),
79
+ className: r(S),
80
80
  style: {
81
81
  width: "100%",
82
82
  height: "100%",
@@ -1 +1 @@
1
- {"version":3,"file":"AdvancedToast.js","names":[],"sources":["../../lib/ui/AdvancedToast.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n} from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { ElasticHeight } from './ElasticHeight';\nimport { Colors, getBgColor, getBorderColor, getTextColor } from './helpers/colors/colors';\nimport { useCountdown } from './hooks/useCountdown';\nimport useResizeObserver from './hooks/useResizeObserver';\n\ninterface Props extends ComponentPropsWithoutRef<'div'> {\n title: string;\n body: string;\n icon: IconicNames;\n isVisible: boolean;\n labels: {\n close: string;\n details: string;\n };\n onClose?: () => void;\n children?: React.ReactNode;\n accentColor?: Colors;\n moreInfoLabel?: string;\n moreInfoHref?: string;\n duration?: false | number;\n toastId: string;\n updateHeight: (id: string, height: number) => void;\n}\n\nexport const AdvancedToast: FunctionComponent<Props> = ({\n className,\n title,\n body,\n icon,\n isVisible,\n labels,\n children,\n accentColor = Colors.orange,\n duration = 10000,\n onClose,\n toastId,\n updateHeight,\n ...attrs\n}) => {\n const id = useId();\n const [isDetailsExpanded, setIsDetailsExpanded] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement>(null!);\n\n const { progress } = useCountdown({ duration, isPaused, isVisible });\n useEffect(() => {\n if (progress === 100) {\n onClose?.();\n }\n }, [progress, onClose]);\n\n const handleMouseDown = () => setIsPaused(true);\n const handleMouseUp = () => setIsPaused(false);\n const handleMouseLeave = () => setIsPaused(false);\n\n useResizeObserver<HTMLDivElement>({\n ref: toastRef,\n onResize: () => {\n if (toastRef.current) {\n updateHeight(toastId, toastRef.current.offsetHeight);\n }\n },\n });\n\n return (\n <div\n ref={toastRef}\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slideRightEnter' : 'animate-slideRightExit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden',\n getBorderColor(accentColor),\n className,\n )}\n role=\"note\"\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n >\n <Icon\n name={icon}\n width=\"30px\"\n className={clsx('flex-shrink-0 pt-4', getTextColor(accentColor))}\n />\n <div className=\"flex flex-1 flex-col gap-12 pe-24 text-b4\">\n <div>\n <p className=\" font-bold\" id={id}>\n {title}\n </p>\n <p>{body}</p>\n </div>\n\n {children && (\n <div>\n <button\n onClick={() => setIsDetailsExpanded(!isDetailsExpanded)}\n aria-expanded={isDetailsExpanded}\n className=\"flex w-fit items-center gap-8 text-b5 font-normal\"\n type=\"button\"\n >\n <span>{labels.details}</span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n style={{ rotate: isDetailsExpanded ? '180deg' : '0deg' }}\n className=\"transition-all duration-300\"\n />\n </button>\n <ElasticHeight isExpanded={isDetailsExpanded}>\n <div className=\"pt-4\">{children}</div>\n </ElasticHeight>\n </div>\n )}\n </div>\n\n {onClose && (\n <button\n aria-describedby={id}\n aria-label={labels.close}\n className=\"absolute end-0 top-0 mt-20 me-13 text-black\"\n onClick={onClose}\n type=\"button\"\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n\n {duration !== false && (\n <div className=\"absolute bottom-0 left-0 right-0 h-4 overflow-hidden rounded-b-16\">\n <div\n className={getBgColor(accentColor)}\n style={{\n width: '100%',\n height: '100%',\n transform: `scaleX(${(100 - progress) / 100})`,\n transformOrigin: 'left',\n transition: 'transform 16ms linear',\n }}\n />\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAqCA,IAAa,KAA2C,EACtD,cACA,UACA,SACA,SACA,cACA,WACA,aACA,iBAAc,EAAO,QACrB,cAAW,KACX,YACA,YACA,iBACA,GAAG,QACC;CACJ,IAAM,IAAK,GAAO,EACZ,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,IAAW,EAAuB,KAAM,EAExC,EAAE,gBAAa,EAAa;EAAE;EAAU;EAAU;EAAW,CAAC;AACpE,SAAgB;AACd,EAAI,MAAa,OACf,KAAW;IAEZ,CAAC,GAAU,EAAQ,CAAC;CAEvB,IAAM,UAAwB,EAAY,GAAK,EACzC,UAAsB,EAAY,GAAM,EACxC,UAAyB,EAAY,GAAM;AAWjD,QATA,EAAkC;EAChC,KAAK;EACL,gBAAgB;AACd,GAAI,EAAS,WACX,EAAa,GAAS,EAAS,QAAQ,aAAa;;EAGzD,CAAC,EAGA,kBAAC,OAAD;EACE,KAAK;EACL,GAAI;EACJ,WAAW,EACT,IAAY,4BAA4B,oCACxC,+HACA,EAAe,EAAY,EAC3B,EACD;EACD,MAAK;EACL,aAAa;EACb,WAAW;EACX,cAAc;YAZhB;GAcE,kBAAC,GAAD;IACE,MAAM;IACN,OAAM;IACN,WAAW,EAAK,sBAAsB,EAAa,EAAY,CAAA;IAC/D,CAAA;GACF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;KAAiB;eAC3B;KACC,CAAA,EACJ,kBAAC,KAAD,EAAA,UAAI,GAAS,CAAA,CACT,EAAA,CAAA,EAEL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,UAAD;KACE,eAAe,EAAqB,CAAC,EAAkB;KACvD,iBAAe;KACf,WAAU;KACV,MAAK;eAJP,CAME,kBAAC,QAAD,EAAA,UAAO,EAAO,SAAe,CAAA,EAC7B,kBAAC,GAAD;MACE,MAAK;MACL,OAAM;MACN,OAAO,EAAE,QAAQ,IAAoB,WAAW,QAAQ;MACxD,WAAU;MACV,CAAA,CAAA;QAEJ,kBAAC,GAAD;KAAe,YAAY;eACzB,kBAAC,OAAD;MAAK,WAAU;MAAQ;MAAe,CAAA;KACxB,CAAA,CACZ,EAAA,CAAA,CAAA;;GAIT,KACC,kBAAC,UAAD;IACE,oBAAkB;IAClB,cAAY,EAAO;IACnB,WAAU;IACV,SAAS;IACT,MAAK;cAEL,kBAAC,GAAD;KAAM,MAAK;KAAe,OAAM;KAAS,CAAA;IAClC,CAAA;GAGV,MAAa,MACZ,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KACE,WAAW,EAAW,EAAY;KAClC,OAAO;MACL,OAAO;MACP,QAAQ;MACR,WAAW,WAAW,MAAM,KAAY,IAAI;MAC5C,iBAAiB;MACjB,YAAY;;KAEd,CAAA;IACE,CAAA"}
1
+ {"version":3,"file":"AdvancedToast.js","names":[],"sources":["../../lib/ui/AdvancedToast.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n} from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { ElasticHeight } from './ElasticHeight';\nimport { Colors, getBgColor, getBorderColor, getTextColor } from './helpers/colors/colors';\nimport { useCountdown } from './hooks/useCountdown';\nimport useResizeObserver from './hooks/useResizeObserver';\n\ninterface Props extends ComponentPropsWithoutRef<'div'> {\n title: string;\n body: string;\n icon: IconicNames;\n isVisible: boolean;\n labels: {\n close: string;\n details: string;\n };\n onClose?: () => void;\n children?: React.ReactNode;\n accentColor?: Colors;\n moreInfoLabel?: string;\n moreInfoHref?: string;\n duration?: false | number;\n toastId: string;\n updateHeight: (id: string, height: number) => void;\n}\n\nexport const AdvancedToast: FunctionComponent<Props> = ({\n className,\n title,\n body,\n icon,\n isVisible,\n labels,\n children,\n accentColor = Colors.orange,\n duration = 10000,\n onClose,\n toastId,\n updateHeight,\n ...attrs\n}) => {\n const id = useId();\n const [isDetailsExpanded, setIsDetailsExpanded] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const toastRef = useRef<HTMLDivElement>(null!);\n\n const { progress } = useCountdown({ duration, isPaused, isVisible });\n useEffect(() => {\n if (progress === 100) {\n onClose?.();\n }\n }, [progress, onClose]);\n\n const handleMouseDown = () => setIsPaused(true);\n const handleMouseUp = () => setIsPaused(false);\n const handleMouseLeave = () => setIsPaused(false);\n\n useResizeObserver<HTMLDivElement>({\n ref: toastRef,\n onResize: () => {\n if (toastRef.current) {\n updateHeight(toastId, toastRef.current.offsetHeight);\n }\n },\n });\n\n return (\n <div\n ref={toastRef}\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slide-right-enter' : 'animate-slide-right-exit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 bg-white p-20 text-black transition-opacity duration-300 border-1 overflow-hidden',\n getBorderColor(accentColor),\n className,\n )}\n role=\"note\"\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n >\n <Icon\n name={icon}\n width=\"30px\"\n className={clsx('flex-shrink-0 pt-4', getTextColor(accentColor))}\n />\n <div className=\"flex flex-1 flex-col gap-12 pe-24 text-b4\">\n <div>\n <p className=\" font-bold\" id={id}>\n {title}\n </p>\n <p>{body}</p>\n </div>\n\n {children && (\n <div>\n <button\n onClick={() => setIsDetailsExpanded(!isDetailsExpanded)}\n aria-expanded={isDetailsExpanded}\n className=\"flex w-fit items-center gap-8 text-b5 font-normal\"\n type=\"button\"\n >\n <span>{labels.details}</span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n style={{ rotate: isDetailsExpanded ? '180deg' : '0deg' }}\n className=\"transition-all duration-300\"\n />\n </button>\n <ElasticHeight isExpanded={isDetailsExpanded}>\n <div className=\"pt-4\">{children}</div>\n </ElasticHeight>\n </div>\n )}\n </div>\n\n {onClose && (\n <button\n aria-describedby={id}\n aria-label={labels.close}\n className=\"absolute end-0 top-0 mt-20 me-13 text-black\"\n onClick={onClose}\n type=\"button\"\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n\n {duration !== false && (\n <div className=\"absolute bottom-0 left-0 right-0 h-4 overflow-hidden rounded-b-16\">\n <div\n className={getBgColor(accentColor)}\n style={{\n width: '100%',\n height: '100%',\n transform: `scaleX(${(100 - progress) / 100})`,\n transformOrigin: 'left',\n transition: 'transform 16ms linear',\n }}\n />\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAqCA,IAAa,KAA2C,EACtD,cACA,UACA,SACA,SACA,cACA,WACA,aACA,iBAAc,EAAO,QACrB,cAAW,KACX,YACA,YACA,iBACA,GAAG,QACC;CACJ,IAAM,IAAK,GAAO,EACZ,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,IAAW,EAAuB,KAAM,EAExC,EAAE,gBAAa,EAAa;EAAE;EAAU;EAAU;EAAW,CAAC;AACpE,SAAgB;AACd,EAAI,MAAa,OACf,KAAW;IAEZ,CAAC,GAAU,EAAQ,CAAC;CAEvB,IAAM,UAAwB,EAAY,GAAK,EACzC,UAAsB,EAAY,GAAM,EACxC,UAAyB,EAAY,GAAM;AAWjD,QATA,EAAkC;EAChC,KAAK;EACL,gBAAgB;AACd,GAAI,EAAS,WACX,EAAa,GAAS,EAAS,QAAQ,aAAa;;EAGzD,CAAC,EAGA,kBAAC,OAAD;EACE,KAAK;EACL,GAAI;EACJ,WAAW,EACT,IAAY,8BAA8B,sCAC1C,+HACA,EAAe,EAAY,EAC3B,EACD;EACD,MAAK;EACL,aAAa;EACb,WAAW;EACX,cAAc;YAZhB;GAcE,kBAAC,GAAD;IACE,MAAM;IACN,OAAM;IACN,WAAW,EAAK,sBAAsB,EAAa,EAAY,CAAA;IAC/D,CAAA;GACF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;KAAiB;eAC3B;KACC,CAAA,EACJ,kBAAC,KAAD,EAAA,UAAI,GAAS,CAAA,CACT,EAAA,CAAA,EAEL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,UAAD;KACE,eAAe,EAAqB,CAAC,EAAkB;KACvD,iBAAe;KACf,WAAU;KACV,MAAK;eAJP,CAME,kBAAC,QAAD,EAAA,UAAO,EAAO,SAAe,CAAA,EAC7B,kBAAC,GAAD;MACE,MAAK;MACL,OAAM;MACN,OAAO,EAAE,QAAQ,IAAoB,WAAW,QAAQ;MACxD,WAAU;MACV,CAAA,CAAA;QAEJ,kBAAC,GAAD;KAAe,YAAY;eACzB,kBAAC,OAAD;MAAK,WAAU;MAAQ;MAAe,CAAA;KACxB,CAAA,CACZ,EAAA,CAAA,CAAA;;GAIT,KACC,kBAAC,UAAD;IACE,oBAAkB;IAClB,cAAY,EAAO;IACnB,WAAU;IACV,SAAS;IACT,MAAK;cAEL,kBAAC,GAAD;KAAM,MAAK;KAAe,OAAM;KAAS,CAAA;IAClC,CAAA;GAGV,MAAa,MACZ,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KACE,WAAW,EAAW,EAAY;KAClC,OAAO;MACL,OAAO;MACP,QAAQ;MACR,WAAW,WAAW,MAAM,KAAY,IAAI;MAC5C,iBAAiB;MACjB,YAAY;;KAEd,CAAA;IACE,CAAA"}
package/ui/BasicToast.js CHANGED
@@ -10,7 +10,7 @@ function l({ className: l, description: u, href: d, icon: f, incentive: p, isVis
10
10
  let S = r(v), C = a(), w = b ?? u;
11
11
  return /* @__PURE__ */ c("div", {
12
12
  ...x,
13
- className: e(m ? "animate-slideRightEnter" : "animate-slideRightExit opacity-0", "relative isolate flex gap-x-20 rounded-16 p-20 transition-opacity duration-300", t(S), n(S), l),
13
+ className: e(m ? "animate-slide-right-enter" : "animate-slide-right-exit opacity-0", "relative isolate flex gap-x-20 rounded-16 p-20 transition-opacity duration-300", t(S), n(S), l),
14
14
  role: "note",
15
15
  children: [
16
16
  f && /* @__PURE__ */ s(o, {
@@ -1 +1 @@
1
- {"version":3,"file":"BasicToast.js","names":[],"sources":["../../lib/ui/BasicToast.tsx"],"sourcesContent":["'use client';\nimport clsx from 'clsx';\nimport { type ComponentPropsWithoutRef, type PropsWithChildren, useId } from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { getBgColor, getComplementaryTextColor, getThemeColor } from './helpers/colors/colors';\nimport { Link } from './Link';\nimport type { Theme } from './types/Theme';\n\nexport interface BasicToastProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * @deprecated use children slot instead\n */\n description?: string;\n href: string;\n icon?: IconicNames;\n incentive: string;\n isVisible: boolean;\n labels: { close: string };\n onClick?: () => void;\n onClose?: () => void;\n theme: Theme;\n title: string;\n}\n\nexport function BasicToast({\n className,\n description,\n href,\n icon,\n incentive,\n isVisible,\n labels,\n onClick,\n onClose,\n theme = 'dark',\n title,\n children,\n ...attrs\n}: PropsWithChildren<BasicToastProps>) {\n const color = getThemeColor(theme);\n const id = useId();\n const content = children ?? description;\n\n return (\n <div\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slideRightEnter' : 'animate-slideRightExit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 p-20 transition-opacity duration-300',\n getBgColor(color),\n getComplementaryTextColor(color),\n className,\n )}\n role=\"note\"\n >\n {icon && <Icon name={icon} width=\"30px\" />}\n <a className=\"group pe-44\" href={href} onClick={onClick}>\n <p className=\"mb-4 text-b3 font-bold\" id={id}>\n {title}\n </p>\n {content && <div className=\"mb-12 text-b4\">{content}</div>}\n <Link component=\"span\" className=\"text-b3 font-bold\" label={incentive} />\n </a>\n {onClose && (\n <button\n aria-describedby={id}\n aria-label={labels.close}\n className={clsx('absolute end-0 top-0 m-20', getComplementaryTextColor(color))}\n onClick={onClose}\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAyBA,SAAgB,EAAW,EACzB,cACA,gBACA,SACA,SACA,cACA,cACA,WACA,YACA,YACA,WAAQ,QACR,UACA,aACA,GAAG,KACkC;CACrC,IAAM,IAAQ,EAAc,EAAM,EAC5B,IAAK,GAAO,EACZ,IAAU,KAAY;AAE5B,QACE,kBAAC,OAAD;EACE,GAAI;EACJ,WAAW,EACT,IAAY,4BAA4B,oCACxC,kFACA,EAAW,EAAM,EACjB,EAA0B,EAAM,EAChC,EACD;EACD,MAAK;YATP;GAWG,KAAQ,kBAAC,GAAD;IAAM,MAAM;IAAM,OAAM;IAAS,CAAA;GAC1C,kBAAC,KAAD;IAAG,WAAU;IAAoB;IAAe;cAAhD;KACE,kBAAC,KAAD;MAAG,WAAU;MAA6B;gBACvC;MACC,CAAA;KACH,KAAW,kBAAC,OAAD;MAAK,WAAU;gBAAiB;MAAc,CAAA;KAC1D,kBAAC,GAAD;MAAM,WAAU;MAAO,WAAU;MAAoB,OAAO;MAAa,CAAA;;;GAE1E,KACC,kBAAC,UAAD;IACE,oBAAkB;IAClB,cAAY,EAAO;IACnB,WAAW,EAAK,6BAA6B,EAA0B,EAAM,CAAC;IAC9E,SAAS;cAET,kBAAC,GAAD;KAAM,MAAK;KAAe,OAAM;KAAS,CAAA;IAClC,CAAA"}
1
+ {"version":3,"file":"BasicToast.js","names":[],"sources":["../../lib/ui/BasicToast.tsx"],"sourcesContent":["'use client';\nimport clsx from 'clsx';\nimport { type ComponentPropsWithoutRef, type PropsWithChildren, useId } from 'react';\n\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport { getBgColor, getComplementaryTextColor, getThemeColor } from './helpers/colors/colors';\nimport { Link } from './Link';\nimport type { Theme } from './types/Theme';\n\nexport interface BasicToastProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * @deprecated use children slot instead\n */\n description?: string;\n href: string;\n icon?: IconicNames;\n incentive: string;\n isVisible: boolean;\n labels: { close: string };\n onClick?: () => void;\n onClose?: () => void;\n theme: Theme;\n title: string;\n}\n\nexport function BasicToast({\n className,\n description,\n href,\n icon,\n incentive,\n isVisible,\n labels,\n onClick,\n onClose,\n theme = 'dark',\n title,\n children,\n ...attrs\n}: PropsWithChildren<BasicToastProps>) {\n const color = getThemeColor(theme);\n const id = useId();\n const content = children ?? description;\n\n return (\n <div\n {...attrs}\n className={clsx(\n isVisible ? 'animate-slide-right-enter' : 'animate-slide-right-exit opacity-0',\n 'relative isolate flex gap-x-20 rounded-16 p-20 transition-opacity duration-300',\n getBgColor(color),\n getComplementaryTextColor(color),\n className,\n )}\n role=\"note\"\n >\n {icon && <Icon name={icon} width=\"30px\" />}\n <a className=\"group pe-44\" href={href} onClick={onClick}>\n <p className=\"mb-4 text-b3 font-bold\" id={id}>\n {title}\n </p>\n {content && <div className=\"mb-12 text-b4\">{content}</div>}\n <Link component=\"span\" className=\"text-b3 font-bold\" label={incentive} />\n </a>\n {onClose && (\n <button\n aria-describedby={id}\n aria-label={labels.close}\n className={clsx('absolute end-0 top-0 m-20', getComplementaryTextColor(color))}\n onClick={onClose}\n >\n <Icon name=\"CrossDefault\" width=\"24px\" />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAyBA,SAAgB,EAAW,EACzB,cACA,gBACA,SACA,SACA,cACA,cACA,WACA,YACA,YACA,WAAQ,QACR,UACA,aACA,GAAG,KACkC;CACrC,IAAM,IAAQ,EAAc,EAAM,EAC5B,IAAK,GAAO,EACZ,IAAU,KAAY;AAE5B,QACE,kBAAC,OAAD;EACE,GAAI;EACJ,WAAW,EACT,IAAY,8BAA8B,sCAC1C,kFACA,EAAW,EAAM,EACjB,EAA0B,EAAM,EAChC,EACD;EACD,MAAK;YATP;GAWG,KAAQ,kBAAC,GAAD;IAAM,MAAM;IAAM,OAAM;IAAS,CAAA;GAC1C,kBAAC,KAAD;IAAG,WAAU;IAAoB;IAAe;cAAhD;KACE,kBAAC,KAAD;MAAG,WAAU;MAA6B;gBACvC;MACC,CAAA;KACH,KAAW,kBAAC,OAAD;MAAK,WAAU;gBAAiB;MAAc,CAAA;KAC1D,kBAAC,GAAD;MAAM,WAAU;MAAO,WAAU;MAAoB,OAAO;MAAa,CAAA;;;GAE1E,KACC,kBAAC,UAAD;IACE,oBAAkB;IAClB,cAAY,EAAO;IACnB,WAAW,EAAK,6BAA6B,EAA0B,EAAM,CAAC;IAC9E,SAAS;cAET,kBAAC,GAAD;KAAM,MAAK;KAAe,OAAM;KAAS,CAAA;IAClC,CAAA"}
@@ -1,10 +1,10 @@
1
1
  import { ComponentPropsWithoutRef, FunctionComponent } from 'react';
2
2
  import { Theme } from './types/Theme';
3
3
  export interface BreadcrumbProps extends ComponentPropsWithoutRef<'nav'> {
4
- items: ({
4
+ items: Array<{
5
5
  href: string;
6
6
  label: string;
7
- } & ComponentPropsWithoutRef<'li'>)[];
7
+ }>;
8
8
  theme?: Theme;
9
9
  }
10
10
  export declare const Breadcrumb: FunctionComponent<BreadcrumbProps>;
package/ui/Breadcrumb.js CHANGED
@@ -1,43 +1,39 @@
1
1
  import { t as e } from "../chunks/clsx.js";
2
- import { getTheme as t } from "./Breadcrumb.themes.js";
3
- import { createElement as n } from "react";
4
- import { Icon as r } from "@clubmed/trident-icons";
5
- import { jsx as i } from "react/jsx-runtime";
2
+ import { getComplementaryTextColor as t, getThemeColor as n } from "./helpers/colors/colors.js";
3
+ import { createElement as r } from "react";
4
+ import { Icon as i } from "@clubmed/trident-icons";
5
+ import { jsx as a } from "react/jsx-runtime";
6
6
  //#region lib/ui/Breadcrumb.tsx
7
- var a = ({ className: a, items: o, theme: s = "light", ...c }) => {
8
- if (o.length == 0) return null;
9
- let [l, u, , ...d] = o, f = d.length ? d[d.length - 1] : o[o.length - 1], p = d.length ? [
10
- l,
11
- u,
7
+ var o = ({ className: o, items: s, theme: c = "light", ...l }) => {
8
+ if (s.length == 0) return null;
9
+ let u = t(n(c)), d = u === "text-white" ? u : "text-middleGrey", [f, p, , ...m] = s, h = m.length ? m[m.length - 1] : s[s.length - 1], g = m.length ? [
10
+ f,
11
+ p,
12
12
  {
13
- label: "",
14
- href: "",
15
- className: "breadcrumb-spacer"
13
+ label: "",
14
+ href: ""
16
15
  },
17
- f
18
- ] : o, { thStart: m, thEnd: h } = t(s);
19
- return /* @__PURE__ */ i("nav", {
20
- role: "navigation",
16
+ h
17
+ ] : s;
18
+ return /* @__PURE__ */ a("nav", {
21
19
  "aria-label": "Breadcrumb",
22
- ...c,
23
- className: e(a, "overflow-hidden"),
24
- "data-name": "Breadcrumb",
25
- children: /* @__PURE__ */ i("ol", {
26
- className: "scrollbar-hidden flex items-center overflow-x-auto font-sans text-b4",
27
- children: p.map(({ label: t, href: a, className: o, ...s }, c) => {
28
- let l = c === p.length - 1, u = a && !l;
29
- return /* @__PURE__ */ n("li", {
30
- ...s,
31
- ...l && { "aria-current": "page" },
32
- className: e("flex shrink-0 items-center", {
33
- [m]: !l,
34
- [h]: l
35
- }, o),
36
- key: `${t}-${c}`
37
- }, u ? /* @__PURE__ */ i("a", {
38
- href: a,
20
+ ...l,
21
+ className: e(o, "overflow-hidden"),
22
+ children: /* @__PURE__ */ a("ul", {
23
+ className: "scrollbar-hidden text-b4 flex items-center overflow-x-auto font-sans",
24
+ children: g.map(({ label: t, href: n }, o) => {
25
+ let s = o === g.length - 1, c = n && !s;
26
+ return /* @__PURE__ */ r("li", {
27
+ ...s && { "aria-current": "page" },
28
+ className: e("flex shrink-0 items-center", { [d]: !s }, {
29
+ "font-bold": s,
30
+ [u]: s
31
+ }),
32
+ key: t
33
+ }, c ? /* @__PURE__ */ a("a", {
34
+ href: n,
39
35
  children: t
40
- }) : t, !l && /* @__PURE__ */ i(r, {
36
+ }) : t, !s && /* @__PURE__ */ a(i, {
41
37
  className: "mx-4",
42
38
  name: "Diamond",
43
39
  width: "14px"
@@ -47,6 +43,6 @@ var a = ({ className: a, items: o, theme: s = "light", ...c }) => {
47
43
  });
48
44
  };
49
45
  //#endregion
50
- export { a as Breadcrumb };
46
+ export { o as Breadcrumb };
51
47
 
52
48
  //# sourceMappingURL=Breadcrumb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../lib/ui/Breadcrumb.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport type { ComponentPropsWithoutRef, FunctionComponent } from 'react';\n\nimport { getTheme } from './Breadcrumb.themes';\n\nimport type { Theme } from './types/Theme';\nimport { Icon } from '@clubmed/trident-icons';\n\nexport interface BreadcrumbProps extends ComponentPropsWithoutRef<'nav'> {\n items: ({\n href: string;\n label: string;\n } & ComponentPropsWithoutRef<'li'>)[];\n theme?: Theme;\n}\n\nexport const Breadcrumb: FunctionComponent<BreadcrumbProps> = ({\n className,\n items,\n theme = 'light',\n ...attrs\n}) => {\n if (items.length == 0) {\n return null;\n }\n\n const [first, second, , ...rest] = items;\n const lastItem = rest.length ? rest[rest.length - 1] : items[items.length - 1];\n const spacer = { label: '', href: '', className: 'breadcrumb-spacer' };\n const itemsToRender = !rest.length ? items : [first, second, spacer, lastItem];\n\n const { thStart, thEnd } = getTheme(theme);\n\n return (\n <nav\n role=\"navigation\"\n aria-label=\"Breadcrumb\"\n {...attrs}\n className={clsx(className, 'overflow-hidden')}\n data-name=\"Breadcrumb\"\n >\n <ol className=\"scrollbar-hidden flex items-center overflow-x-auto font-sans text-b4\">\n {itemsToRender.map(({ label, href, className, ...attrs }, index) => {\n const isLast = index === itemsToRender.length - 1;\n const isLink = href && !isLast;\n return (\n <li\n {...attrs}\n {...(isLast && { 'aria-current': 'page' })}\n className={clsx(\n 'flex shrink-0 items-center',\n {\n [thStart]: !isLast,\n [thEnd]: isLast,\n },\n className,\n )}\n key={`${label}-${index}`}\n >\n {isLink ? <a href={href}>{label}</a> : label}\n {!isLast && <Icon className=\"mx-4\" name=\"Diamond\" width=\"14px\" />}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n};\n"],"mappings":";;;;;;AAgBA,IAAa,KAAkD,EAC7D,cACA,UACA,WAAQ,SACR,GAAG,QACC;AACJ,KAAI,EAAM,UAAU,EAClB,QAAO;CAGT,IAAM,CAAC,GAAO,KAAU,GAAG,KAAQ,GAC7B,IAAW,EAAK,SAAS,EAAK,EAAK,SAAS,KAAK,EAAM,EAAM,SAAS,IAEtE,IAAiB,EAAK,SAAiB;EAAC;EAAO;EADtC;GAAE,OAAO;GAAI,MAAM;GAAI,WAAW;GAAqB;EACD;EAAS,GAAzC,GAE/B,EAAE,YAAS,aAAU,EAAS,EAAM;AAE1C,QACE,kBAAC,OAAD;EACE,MAAK;EACL,cAAW;EACX,GAAI;EACJ,WAAW,EAAK,GAAW,kBAAkB;EAC7C,aAAU;YAEV,kBAAC,MAAD;GAAI,WAAU;aACX,EAAc,KAAK,EAAE,UAAO,SAAM,cAAW,GAAG,KAAS,MAAU;IAClE,IAAM,IAAS,MAAU,EAAc,SAAS,GAC1C,IAAS,KAAQ,CAAC;AACxB,WACE,kBAAC,MAAD;KACE,GAAI;KACJ,GAAK,KAAU,EAAE,gBAAgB,QAAQ;KACzC,WAAW,EACT,8BACA;OACG,IAAU,CAAC;OACX,IAAQ;MACV,EACD,EACD;KACD,KAAK,GAAG,EAAM,GAAG;KAId,EAFF,IAAS,kBAAC,KAAD;KAAS;eAAO;KAAU,CAAA,GAAG,GACtC,CAAC,KAAU,kBAAC,GAAD;KAAM,WAAU;KAAO,MAAK;KAAU,OAAM;KAAS,CAAA,CAC9D;KAEP;GACC,CAAA;EACD,CAAA"}
1
+ {"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../lib/ui/Breadcrumb.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport type { ComponentPropsWithoutRef, FunctionComponent } from 'react';\n\nimport type { Theme } from './types/Theme';\nimport { Icon } from '@clubmed/trident-icons';\nimport { getComplementaryTextColor, getThemeColor } from './helpers/colors/colors';\n\nexport interface BreadcrumbProps extends ComponentPropsWithoutRef<'nav'> {\n items: Array<{\n href: string;\n label: string;\n }>;\n theme?: Theme;\n}\n\nexport const Breadcrumb: FunctionComponent<BreadcrumbProps> = ({\n className,\n items,\n theme = 'light',\n ...attrs\n}) => {\n if (items.length == 0) {\n return null;\n }\n\n const themeColor = getThemeColor(theme);\n const accentColor = getComplementaryTextColor(themeColor);\n const color = accentColor === 'text-white' ? accentColor : 'text-middleGrey';\n\n const [first, second, , ...rest] = items;\n const lastItem = rest.length ? rest[rest.length - 1] : items[items.length - 1];\n const spacer = { label: '', href: '' };\n const itemsToRender = !rest.length ? items : [first, second, spacer, lastItem];\n\n return (\n <nav aria-label=\"Breadcrumb\" {...attrs} className={clsx(className, 'overflow-hidden')}>\n <ul className=\"scrollbar-hidden text-b4 flex items-center overflow-x-auto font-sans\">\n {itemsToRender.map(({ label, href }, index) => {\n const isLast = index === itemsToRender.length - 1;\n const isLink = href && !isLast;\n\n return (\n <li\n {...(isLast && { 'aria-current': 'page' })}\n className={clsx(\n 'flex shrink-0 items-center',\n { [color]: !isLast },\n {\n 'font-bold': isLast,\n [accentColor]: isLast,\n },\n )}\n key={label}\n >\n {isLink ? <a href={href}>{label}</a> : label}\n {!isLast && <Icon className=\"mx-4\" name=\"Diamond\" width=\"14px\" />}\n </li>\n );\n })}\n </ul>\n </nav>\n );\n};\n"],"mappings":";;;;;;AAeA,IAAa,KAAkD,EAC7D,cACA,UACA,WAAQ,SACR,GAAG,QACC;AACJ,KAAI,EAAM,UAAU,EAClB,QAAO;CAIT,IAAM,IAAc,EADD,EAAc,EAAM,CACkB,EACnD,IAAQ,MAAgB,eAAe,IAAc,mBAErD,CAAC,GAAO,KAAU,GAAG,KAAQ,GAC7B,IAAW,EAAK,SAAS,EAAK,EAAK,SAAS,KAAK,EAAM,EAAM,SAAS,IAEtE,IAAiB,EAAK,SAAiB;EAAC;EAAO;EADtC;GAAE,OAAO;GAAK,MAAM;GAAI;EAC8B;EAAS,GAAzC;AAErC,QACE,kBAAC,OAAD;EAAK,cAAW;EAAa,GAAI;EAAO,WAAW,EAAK,GAAW,kBAAkB;YACnF,kBAAC,MAAD;GAAI,WAAU;aACX,EAAc,KAAK,EAAE,UAAO,WAAQ,MAAU;IAC7C,IAAM,IAAS,MAAU,EAAc,SAAS,GAC1C,IAAS,KAAQ,CAAC;AAExB,WACE,kBAAC,MAAD;KACE,GAAK,KAAU,EAAE,gBAAgB,QAAQ;KACzC,WAAW,EACT,8BACA,GAAG,IAAQ,CAAC,GAAQ,EACpB;MACE,aAAa;OACZ,IAAc;MAChB,CACF;KACD,KAAK;KAIF,EAFF,IAAS,kBAAC,KAAD;KAAS;eAAO;KAAU,CAAA,GAAG,GACtC,CAAC,KAAU,kBAAC,GAAD;KAAM,WAAU;KAAO,MAAK;KAAU,OAAM;KAAS,CAAA,CAC9D;KAEP;GACC,CAAA;EACD,CAAA"}
@@ -43,7 +43,7 @@ var d = ({ label: d, showCheckIcon: f = !1, children: p, expanded: m, defaultExp
43
43
  children: /* @__PURE__ */ u("div", {
44
44
  ref: O,
45
45
  className: e("absolute top-0 grid transition-all duration-500", !M && [
46
- "w-240 rounded-pill border-transparent",
46
+ "w-240 rounded-pill-transitionable border-transparent",
47
47
  t(y),
48
48
  n(b)
49
49
  ], M && [
@@ -1 +1 @@
1
- {"version":3,"file":"ChoiceExpander.js","names":[],"sources":["../../lib/ui/ChoiceExpander.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport { getBgColor, getTextColor } from './helpers/colors/colors';\nimport type { Colors } from './types/Colors';\n\nexport interface ChoiceExpanderProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Text shown when collapsed (e.g., \"From $255\")\n */\n label: string;\n\n /**\n * Show check icon in collapsed state (selected variant)\n */\n showCheckIcon?: boolean;\n\n /**\n * Content shown when expanded\n */\n children: ReactNode;\n\n /**\n * Controlled state - if provided, component is controlled\n */\n expanded?: boolean;\n\n /**\n * Initial state for uncontrolled mode\n */\n defaultExpanded?: boolean;\n\n /**\n * Callback when expanded state changes\n */\n onExpandedChange?: (isExpanded: boolean) => void;\n\n /**\n * Disable interaction\n */\n disabled?: boolean;\n\n /**\n * Custom aria-label for button\n */\n ariaLabel?: string;\n\n /**\n * Background color for unexpanded button state\n */\n buttonBgColor?: Colors;\n\n /**\n * Text color for unexpanded button state\n */\n buttonTextColor?: Colors;\n\n /**\n * collapse label for screen readers\n */\n collapseLabel: string;\n\n /**\n * expand label for screen readers\n */\n expandLabel: string;\n}\n\nexport const ChoiceExpander: FunctionComponent<ChoiceExpanderProps> = ({\n label,\n showCheckIcon = false,\n children,\n expanded,\n defaultExpanded = false,\n onExpandedChange,\n disabled = false,\n ariaLabel,\n buttonBgColor = 'black',\n buttonTextColor = 'white',\n collapseLabel,\n expandLabel,\n className,\n ...props\n}) => {\n const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);\n const contentId = useId();\n const morphContainerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLButtonElement>(null);\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const hasInteractedRef = useRef(false);\n\n const isExpanded = expanded !== undefined ? expanded : internalExpanded;\n\n const handleToggle = useCallback(() => {\n if (disabled) return;\n\n hasInteractedRef.current = true;\n const newState = !isExpanded;\n\n if (expanded === undefined) {\n setInternalExpanded(newState);\n }\n\n onExpandedChange?.(newState);\n }, [disabled, isExpanded, expanded, onExpandedChange]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n handleToggle();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isExpanded, handleToggle]);\n\n useEffect(() => {\n if (isExpanded && closeButtonRef.current) {\n closeButtonRef.current.focus();\n } else if (!isExpanded && hasInteractedRef.current && triggerButtonRef.current) {\n triggerButtonRef.current.focus();\n }\n }, [isExpanded]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (morphContainerRef.current && !morphContainerRef.current.contains(event.target as Node)) {\n handleToggle();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isExpanded, handleToggle]);\n\n return (\n <div\n className={clsx('relative flex items-center justify-center', className)}\n data-name=\"ChoiceExpander\"\n data-testid=\"choice-expander\"\n style={{ width: '240px', height: 48 }}\n {...props}\n >\n <div\n ref={morphContainerRef}\n className={clsx(\n 'absolute top-0 grid transition-all duration-500',\n !isExpanded && [\n 'w-240 rounded-pill border-transparent',\n getBgColor(buttonBgColor),\n getTextColor(buttonTextColor),\n ],\n isExpanded && [\n 'w-324 rounded-16 bg-white text-black border border-gray-900',\n 'z-10',\n disabled && 'opacity-50',\n ],\n )}\n >\n <button\n ref={triggerButtonRef}\n type=\"button\"\n data-testid=\"choice-expander-button\"\n aria-expanded={isExpanded}\n aria-controls={contentId}\n aria-label={ariaLabel || label}\n disabled={disabled}\n onClick={handleToggle}\n className={clsx(\n 'flex items-center justify-center w-240 mx-auto relative gap-20 transition-opacity duration-200',\n 'rounded-pill focus-visible:ring focus-visible:ring-8 focus-visible:ring-lavender/20 outline-none px-20 py-12 ',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n '[@supports(anchor-name:_--label-anchor)]:[--anchorSupport:1]',\n )}\n >\n {/* invisible top middle anchor position */}\n <div\n aria-hidden=\"true\"\n className=\"absolute h-24 w-24 mx-auto pointer-events-none\"\n style={{ anchorName: '--middle-anchor' } as React.CSSProperties}\n ></div>\n <span className=\"text-b3 flex items-center font-semibold\">\n {/* label anchor */}\n <span\n className={clsx('transition-opacity duration-200 pe-8', isExpanded && 'opacity-0')}\n >\n {label}\n </span>\n <div\n className=\"h-24 w-24\"\n style={{ anchorName: '--label-anchor' } as React.CSSProperties}\n aria-hidden=\"true\"\n >\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx(\n isExpanded ? 'absolute left-[calc(50%-12px)] rotate-180' : 'rotate-[0deg]',\n )}\n style={\n {\n transition: 'rotate 0.3s, left 0.3s',\n opacity: 'calc((1 - var(--anchorSupport)) * 1)',\n } as React.CSSProperties\n }\n />\n </div>\n <span className=\"sr-only\">{isExpanded ? collapseLabel : expandLabel}</span>\n </span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('absolute', isExpanded ? 'rotate-180' : 'rotate-[0deg]')}\n style={\n {\n positionAnchor: isExpanded ? '--middle-anchor' : '--label-anchor',\n left: 'anchor(left)',\n top: 'anchor(top)',\n transition: 'left 0.3s, rotate 0.3s',\n } as React.CSSProperties\n }\n />\n {showCheckIcon && (\n <Icon\n name=\"CheckDefault\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('transition-opacity duration-200', isExpanded && 'opacity-0')}\n />\n )}\n </button>\n\n <div\n className={clsx(\n 'grid overflow-hidden transition-[grid-template-rows,opacity] duration-500',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr] opacity-0',\n )}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-8 pb-8\" id={contentId}>\n {children}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ChoiceExpander.js","names":[],"sources":["../../lib/ui/ChoiceExpander.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n type ReactNode,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { Icon } from '@clubmed/trident-icons';\nimport { getBgColor, getTextColor } from './helpers/colors/colors';\nimport type { Colors } from './types/Colors';\n\nexport interface ChoiceExpanderProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Text shown when collapsed (e.g., \"From $255\")\n */\n label: string;\n\n /**\n * Show check icon in collapsed state (selected variant)\n */\n showCheckIcon?: boolean;\n\n /**\n * Content shown when expanded\n */\n children: ReactNode;\n\n /**\n * Controlled state - if provided, component is controlled\n */\n expanded?: boolean;\n\n /**\n * Initial state for uncontrolled mode\n */\n defaultExpanded?: boolean;\n\n /**\n * Callback when expanded state changes\n */\n onExpandedChange?: (isExpanded: boolean) => void;\n\n /**\n * Disable interaction\n */\n disabled?: boolean;\n\n /**\n * Custom aria-label for button\n */\n ariaLabel?: string;\n\n /**\n * Background color for unexpanded button state\n */\n buttonBgColor?: Colors;\n\n /**\n * Text color for unexpanded button state\n */\n buttonTextColor?: Colors;\n\n /**\n * collapse label for screen readers\n */\n collapseLabel: string;\n\n /**\n * expand label for screen readers\n */\n expandLabel: string;\n}\n\nexport const ChoiceExpander: FunctionComponent<ChoiceExpanderProps> = ({\n label,\n showCheckIcon = false,\n children,\n expanded,\n defaultExpanded = false,\n onExpandedChange,\n disabled = false,\n ariaLabel,\n buttonBgColor = 'black',\n buttonTextColor = 'white',\n collapseLabel,\n expandLabel,\n className,\n ...props\n}) => {\n const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);\n const contentId = useId();\n const morphContainerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLButtonElement>(null);\n const triggerButtonRef = useRef<HTMLButtonElement>(null);\n const hasInteractedRef = useRef(false);\n\n const isExpanded = expanded !== undefined ? expanded : internalExpanded;\n\n const handleToggle = useCallback(() => {\n if (disabled) return;\n\n hasInteractedRef.current = true;\n const newState = !isExpanded;\n\n if (expanded === undefined) {\n setInternalExpanded(newState);\n }\n\n onExpandedChange?.(newState);\n }, [disabled, isExpanded, expanded, onExpandedChange]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n handleToggle();\n }\n };\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isExpanded, handleToggle]);\n\n useEffect(() => {\n if (isExpanded && closeButtonRef.current) {\n closeButtonRef.current.focus();\n } else if (!isExpanded && hasInteractedRef.current && triggerButtonRef.current) {\n triggerButtonRef.current.focus();\n }\n }, [isExpanded]);\n\n useEffect(() => {\n if (!isExpanded) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (morphContainerRef.current && !morphContainerRef.current.contains(event.target as Node)) {\n handleToggle();\n }\n };\n\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isExpanded, handleToggle]);\n\n return (\n <div\n className={clsx('relative flex items-center justify-center', className)}\n data-name=\"ChoiceExpander\"\n data-testid=\"choice-expander\"\n style={{ width: '240px', height: 48 }}\n {...props}\n >\n <div\n ref={morphContainerRef}\n className={clsx(\n 'absolute top-0 grid transition-all duration-500',\n !isExpanded && [\n 'w-240 rounded-pill-transitionable border-transparent',\n getBgColor(buttonBgColor),\n getTextColor(buttonTextColor),\n ],\n isExpanded && [\n 'w-324 rounded-16 bg-white text-black border border-gray-900',\n 'z-10',\n disabled && 'opacity-50',\n ],\n )}\n >\n <button\n ref={triggerButtonRef}\n type=\"button\"\n data-testid=\"choice-expander-button\"\n aria-expanded={isExpanded}\n aria-controls={contentId}\n aria-label={ariaLabel || label}\n disabled={disabled}\n onClick={handleToggle}\n className={clsx(\n 'flex items-center justify-center w-240 mx-auto relative gap-20 transition-opacity duration-200',\n 'rounded-pill focus-visible:ring focus-visible:ring-8 focus-visible:ring-lavender/20 outline-none px-20 py-12 ',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n '[@supports(anchor-name:_--label-anchor)]:[--anchorSupport:1]',\n )}\n >\n {/* invisible top middle anchor position */}\n <div\n aria-hidden=\"true\"\n className=\"absolute h-24 w-24 mx-auto pointer-events-none\"\n style={{ anchorName: '--middle-anchor' } as React.CSSProperties}\n ></div>\n <span className=\"text-b3 flex items-center font-semibold\">\n {/* label anchor */}\n <span\n className={clsx('transition-opacity duration-200 pe-8', isExpanded && 'opacity-0')}\n >\n {label}\n </span>\n <div\n className=\"h-24 w-24\"\n style={{ anchorName: '--label-anchor' } as React.CSSProperties}\n aria-hidden=\"true\"\n >\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx(\n isExpanded ? 'absolute left-[calc(50%-12px)] rotate-180' : 'rotate-[0deg]',\n )}\n style={\n {\n transition: 'rotate 0.3s, left 0.3s',\n opacity: 'calc((1 - var(--anchorSupport)) * 1)',\n } as React.CSSProperties\n }\n />\n </div>\n <span className=\"sr-only\">{isExpanded ? collapseLabel : expandLabel}</span>\n </span>\n <Icon\n name=\"ArrowDefaultDown\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('absolute', isExpanded ? 'rotate-180' : 'rotate-[0deg]')}\n style={\n {\n positionAnchor: isExpanded ? '--middle-anchor' : '--label-anchor',\n left: 'anchor(left)',\n top: 'anchor(top)',\n transition: 'left 0.3s, rotate 0.3s',\n } as React.CSSProperties\n }\n />\n {showCheckIcon && (\n <Icon\n name=\"CheckDefault\"\n width=\"24px\"\n aria-hidden=\"true\"\n className={clsx('transition-opacity duration-200', isExpanded && 'opacity-0')}\n />\n )}\n </button>\n\n <div\n className={clsx(\n 'grid overflow-hidden transition-[grid-template-rows,opacity] duration-500',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr] opacity-0',\n )}\n >\n <div className=\"overflow-hidden\">\n <div className=\"px-8 pb-8\" id={contentId}>\n {children}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
package/ui/Dropdown.d.ts CHANGED
@@ -1,6 +1,23 @@
1
- import { ComponentPropsWithoutRef, PropsWithChildren } from 'react';
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
2
  import { IconicNames } from '@clubmed/trident-icons';
3
- export interface DropdownProps extends ComponentPropsWithoutRef<'button'> {
3
+ interface DropdownRenderContext {
4
+ close: () => void;
5
+ open: boolean;
6
+ toggle: () => void;
7
+ }
8
+ type DropdownChildren = ReactNode | ((context: DropdownRenderContext) => ReactNode);
9
+ export interface DropdownProps extends Omit<ComponentPropsWithoutRef<'button'>, 'children'> {
10
+ children?: DropdownChildren;
4
11
  icon?: IconicNames;
5
12
  }
6
- export declare function Dropdown({ icon, className, children: initialChildren, ...attrs }: PropsWithChildren<DropdownProps>): import("react/jsx-runtime").JSX.Element;
13
+ export declare function useDropdown(initialChildren?: DropdownChildren): {
14
+ children: ReactNode[];
15
+ close: () => void;
16
+ containerRef: import('react').RefObject<HTMLDivElement | null>;
17
+ isLeaving: boolean;
18
+ label: ReactNode[];
19
+ open: boolean;
20
+ toggle: () => void;
21
+ };
22
+ export declare function Dropdown({ icon, className, children: initialChildren, ...attrs }: DropdownProps): import("react/jsx-runtime").JSX.Element;
23
+ export {};
package/ui/Dropdown.js CHANGED
@@ -5,43 +5,77 @@ import { useCallback as r, useEffect as i, useRef as a, useState as o } from "re
5
5
  import { Icon as s } from "@clubmed/trident-icons";
6
6
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
7
  //#region lib/ui/Dropdown.tsx
8
- function u({ icon: u = "ArrowOutlinedDown", className: d, children: f, ...p }) {
9
- let { label: m, children: h } = n(f, ["label"]), [g, _] = o(!1), v = a(null), y = a(g), b = y.current, x = !g && b;
10
- y.current = g;
11
- let S = r(() => {
12
- _((e) => !e);
13
- }, []);
8
+ function u(e) {
9
+ let [t, s] = o(!1), c = a(null), l = a(t), u = l.current, d = !t && u;
10
+ l.current = t;
11
+ let f = r(() => {
12
+ s((e) => !e);
13
+ }, []), p = r(() => {
14
+ s(!1);
15
+ }, []), m = typeof e == "function" ? e({
16
+ close: p,
17
+ open: t,
18
+ toggle: f
19
+ }) : e, { label: h, children: g } = n(m, ["label"]);
14
20
  return i(() => {
15
- if (!g) return;
21
+ if (!c.current) return;
22
+ let e = c.current.querySelectorAll(".dropdown-panel a[href], .dropdown-panel [data-dropdown-item]"), t = Array.from(e, (e) => {
23
+ let t = () => {
24
+ p();
25
+ };
26
+ return e.addEventListener("click", t), {
27
+ handleItemClick: t,
28
+ item: e
29
+ };
30
+ });
31
+ return () => {
32
+ t.forEach(({ handleItemClick: e, item: t }) => {
33
+ t.removeEventListener("click", e);
34
+ });
35
+ };
36
+ }, [p, m]), i(() => {
37
+ if (!t) return;
16
38
  let e = (e) => {
17
- !v.current || e.composedPath().includes(v.current) || _(!1);
39
+ !c.current || e.composedPath().includes(c.current) || p();
18
40
  };
19
- return document.addEventListener("pointerdown", e), () => {
20
- document.removeEventListener("pointerdown", e);
41
+ return document.addEventListener("click", e), () => {
42
+ document.removeEventListener("click", e);
21
43
  };
22
- }, [g]), /* @__PURE__ */ l("div", {
23
- ref: v,
24
- className: t("flex items-center gap-8 relative", d),
44
+ }, [p, t]), {
45
+ children: g,
46
+ close: p,
47
+ containerRef: c,
48
+ isLeaving: d,
49
+ label: h,
50
+ open: t,
51
+ toggle: f
52
+ };
53
+ }
54
+ function d({ icon: n = "ArrowOutlinedDown", className: r, children: i, ...a }) {
55
+ let { children: o, containerRef: d, isLeaving: f, label: p, open: m, toggle: h } = u(i);
56
+ return /* @__PURE__ */ l("div", {
57
+ ref: d,
58
+ className: t("flex items-center gap-8 relative", r),
25
59
  children: [/* @__PURE__ */ l("button", {
26
60
  tabIndex: -1,
27
- ...p,
61
+ ...a,
28
62
  className: "flex gap-8 items-center relative",
29
- onClick: S,
30
- children: [m, /* @__PURE__ */ c(s, {
31
- name: u,
63
+ onClick: h,
64
+ children: [p, /* @__PURE__ */ c(s, {
65
+ name: n,
32
66
  className: "w-30"
33
67
  })]
34
68
  }), /* @__PURE__ */ c("div", {
35
- className: t(e("z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]", {
36
- "animate-zoomIn": g,
37
- "animate-zoomOut": !g && x,
38
- "opacity-0 scale-90 pointer-events-none": !g && !x
69
+ className: t(e("dropdown-panel z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]", {
70
+ "animate-zoomIn": m,
71
+ "animate-zoomOut": !m && f,
72
+ "opacity-0 scale-90 pointer-events-none": !m && !f
39
73
  })),
40
- children: h
74
+ children: o
41
75
  })]
42
76
  });
43
77
  }
44
78
  //#endregion
45
- export { u as Dropdown };
79
+ export { d as Dropdown, u as useDropdown };
46
80
 
47
81
  //# sourceMappingURL=Dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","names":[],"sources":["../../lib/ui/Dropdown.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type PropsWithChildren,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport clsx from 'clsx';\nimport { twMerge } from '@/ui/helpers/twMerge';\nimport { useSlots } from '@/ui/hooks/useSlots';\n\nexport interface DropdownProps extends ComponentPropsWithoutRef<'button'> {\n icon?: IconicNames;\n}\n\nexport function Dropdown({\n icon = 'ArrowOutlinedDown',\n className,\n children: initialChildren,\n ...attrs\n}: PropsWithChildren<DropdownProps>) {\n const { label, children } = useSlots(initialChildren, ['label']);\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const wasVisibleRef = useRef(open);\n const wasVisible = wasVisibleRef.current;\n const isLeaving = !open && wasVisible;\n\n // update ref for next render\n wasVisibleRef.current = open;\n\n const onClick = useCallback(() => {\n setOpen((prev) => !prev);\n }, []);\n\n // Close overlay when clicking outside using composedPath\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const handlePointerDown = (event: PointerEvent) => {\n if (!containerRef.current || event.composedPath().includes(containerRef.current)) {\n return;\n }\n\n setOpen(false);\n };\n\n document.addEventListener('pointerdown', handlePointerDown);\n return () => {\n document.removeEventListener('pointerdown', handlePointerDown);\n };\n }, [open]);\n\n return (\n <div ref={containerRef} className={twMerge('flex items-center gap-8 relative', className)}>\n <button\n tabIndex={-1}\n {...attrs}\n className=\"flex gap-8 items-center relative\"\n onClick={onClick}\n >\n {label}\n\n <Icon name={icon} className=\"w-30\" />\n </button>\n\n <div\n className={twMerge(\n clsx(\n 'z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]',\n {\n 'animate-zoomIn': open,\n 'animate-zoomOut': !open && isLeaving,\n 'opacity-0 scale-90 pointer-events-none': !open && !isLeaving,\n },\n ),\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,EAAS,EACvB,UAAO,qBACP,cACA,UAAU,GACV,GAAG,KACgC;CACnC,IAAM,EAAE,UAAO,gBAAa,EAAS,GAAiB,CAAC,QAAQ,CAAC,EAC1D,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAe,EAAuB,KAAK,EAC3C,IAAgB,EAAO,EAAK,EAC5B,IAAa,EAAc,SAC3B,IAAY,CAAC,KAAQ;AAG3B,GAAc,UAAU;CAExB,IAAM,IAAU,QAAkB;AAChC,KAAS,MAAS,CAAC,EAAK;IACvB,EAAE,CAAC;AAsBN,QAnBA,QAAgB;AACd,MAAI,CAAC,EACH;EAGF,IAAM,KAAqB,MAAwB;AAC7C,IAAC,EAAa,WAAW,EAAM,cAAc,CAAC,SAAS,EAAa,QAAQ,IAIhF,EAAQ,GAAM;;AAIhB,SADA,SAAS,iBAAiB,eAAe,EAAkB,QAC9C;AACX,YAAS,oBAAoB,eAAe,EAAkB;;IAE/D,CAAC,EAAK,CAAC,EAGR,kBAAC,OAAD;EAAK,KAAK;EAAc,WAAW,EAAQ,oCAAoC,EAAU;YAAzF,CACE,kBAAC,UAAD;GACE,UAAU;GACV,GAAI;GACJ,WAAU;GACD;aAJX,CAMG,GAED,kBAAC,GAAD;IAAM,MAAM;IAAM,WAAU;IAAS,CAAA,CAC9B;MAET,kBAAC,OAAD;GACE,WAAW,EACT,EACE,+LACA;IACE,kBAAkB;IAClB,mBAAmB,CAAC,KAAQ;IAC5B,0CAA0C,CAAC,KAAQ,CAAC;IACrD,CACF,CACF;GAEA;GACG,CAAA,CACF"}
1
+ {"version":3,"file":"Dropdown.js","names":[],"sources":["../../lib/ui/Dropdown.tsx"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { Icon, type IconicNames } from '@clubmed/trident-icons';\nimport clsx from 'clsx';\nimport { twMerge } from '@/ui/helpers/twMerge';\nimport { useSlots } from '@/ui/hooks/useSlots';\n\ninterface DropdownRenderContext {\n close: () => void;\n open: boolean;\n toggle: () => void;\n}\n\ntype DropdownChildren = ReactNode | ((context: DropdownRenderContext) => ReactNode);\n\nexport interface DropdownProps extends Omit<ComponentPropsWithoutRef<'button'>, 'children'> {\n children?: DropdownChildren;\n icon?: IconicNames;\n}\n\nexport function useDropdown(initialChildren?: DropdownChildren) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n const wasVisibleRef = useRef(open);\n const wasVisible = wasVisibleRef.current;\n const isLeaving = !open && wasVisible;\n\n // update ref for next render\n wasVisibleRef.current = open;\n\n const toggle = useCallback(() => {\n setOpen((prev) => !prev);\n }, []);\n\n const close = useCallback(() => {\n setOpen(false);\n }, []);\n\n const renderedChildren =\n typeof initialChildren === 'function'\n ? initialChildren({ close, open, toggle })\n : initialChildren;\n\n const { label, children } = useSlots(renderedChildren, ['label']);\n\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const items = containerRef.current.querySelectorAll(\n '.dropdown-panel a[href], .dropdown-panel [data-dropdown-item]',\n );\n const listeners = Array.from(items, (item) => {\n const handleItemClick = () => {\n close();\n };\n item.addEventListener('click', handleItemClick);\n return { handleItemClick, item };\n });\n\n return () => {\n listeners.forEach(({ handleItemClick, item }) => {\n item.removeEventListener('click', handleItemClick);\n });\n };\n }, [close, renderedChildren]);\n\n // Close overlay when clicking outside using composedPath\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const handleOutsideClick = (event: PointerEvent) => {\n if (!containerRef.current || event.composedPath().includes(containerRef.current)) {\n return;\n }\n\n close();\n };\n\n document.addEventListener('click', handleOutsideClick);\n return () => {\n document.removeEventListener('click', handleOutsideClick);\n };\n }, [close, open]);\n\n return {\n children,\n close,\n containerRef,\n isLeaving,\n label,\n open,\n toggle,\n };\n}\n\nexport function Dropdown({\n icon = 'ArrowOutlinedDown',\n className,\n children: initialChildren,\n ...attrs\n}: DropdownProps) {\n const { children, containerRef, isLeaving, label, open, toggle } = useDropdown(initialChildren);\n\n return (\n <div ref={containerRef} className={twMerge('flex items-center gap-8 relative', className)}>\n <button\n tabIndex={-1}\n {...attrs}\n className=\"flex gap-8 items-center relative\"\n onClick={toggle}\n >\n {label}\n\n <Icon name={icon} className=\"w-30\" />\n </button>\n\n <div\n className={twMerge(\n clsx(\n 'dropdown-panel z-5 flex items-center gap-12 bg-white rounded-16 border-1 border-lightGrey absolute top-[calc(100%+8px)] right-0 text-black p-20 min-w-[120px] origin-center will-change[transform,opacity]',\n {\n 'animate-zoomIn': open,\n 'animate-zoomOut': !open && isLeaving,\n 'opacity-0 scale-90 pointer-events-none': !open && !isLeaving,\n },\n ),\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AA0BA,SAAgB,EAAY,GAAoC;CAC9D,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAe,EAAuB,KAAK,EAC3C,IAAgB,EAAO,EAAK,EAC5B,IAAa,EAAc,SAC3B,IAAY,CAAC,KAAQ;AAG3B,GAAc,UAAU;CAExB,IAAM,IAAS,QAAkB;AAC/B,KAAS,MAAS,CAAC,EAAK;IACvB,EAAE,CAAC,EAEA,IAAQ,QAAkB;AAC9B,IAAQ,GAAM;IACb,EAAE,CAAC,EAEA,IACJ,OAAO,KAAoB,aACvB,EAAgB;EAAE;EAAO;EAAM;EAAQ,CAAC,GACxC,GAEA,EAAE,UAAO,gBAAa,EAAS,GAAkB,CAAC,QAAQ,CAAC;AA6CjE,QA3CA,QAAgB;AACd,MAAI,CAAC,EAAa,QAChB;EAGF,IAAM,IAAQ,EAAa,QAAQ,iBACjC,gEACD,EACK,IAAY,MAAM,KAAK,IAAQ,MAAS;GAC5C,IAAM,UAAwB;AAC5B,OAAO;;AAGT,UADA,EAAK,iBAAiB,SAAS,EAAgB,EACxC;IAAE;IAAiB;IAAM;IAChC;AAEF,eAAa;AACX,KAAU,SAAS,EAAE,oBAAiB,cAAW;AAC/C,MAAK,oBAAoB,SAAS,EAAgB;KAClD;;IAEH,CAAC,GAAO,EAAiB,CAAC,EAG7B,QAAgB;AACd,MAAI,CAAC,EACH;EAGF,IAAM,KAAsB,MAAwB;AAC9C,IAAC,EAAa,WAAW,EAAM,cAAc,CAAC,SAAS,EAAa,QAAQ,IAIhF,GAAO;;AAIT,SADA,SAAS,iBAAiB,SAAS,EAAmB,QACzC;AACX,YAAS,oBAAoB,SAAS,EAAmB;;IAE1D,CAAC,GAAO,EAAK,CAAC,EAEV;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;AAGH,SAAgB,EAAS,EACvB,UAAO,qBACP,cACA,UAAU,GACV,GAAG,KACa;CAChB,IAAM,EAAE,aAAU,iBAAc,cAAW,UAAO,SAAM,cAAW,EAAY,EAAgB;AAE/F,QACE,kBAAC,OAAD;EAAK,KAAK;EAAc,WAAW,EAAQ,oCAAoC,EAAU;YAAzF,CACE,kBAAC,UAAD;GACE,UAAU;GACV,GAAI;GACJ,WAAU;GACV,SAAS;aAJX,CAMG,GAED,kBAAC,GAAD;IAAM,MAAM;IAAM,WAAU;IAAS,CAAA,CAC9B;MAET,kBAAC,OAAD;GACE,WAAW,EACT,EACE,8MACA;IACE,kBAAkB;IAClB,mBAAmB,CAAC,KAAQ;IAC5B,0CAA0C,CAAC,KAAQ,CAAC;IACrD,CACF,CACF;GAEA;GACG,CAAA,CACF"}
@@ -3,7 +3,6 @@ interface ElasticHeightProps extends ComponentPropsWithoutRef<'div'> {
3
3
  innerClassName?: string;
4
4
  isExpanded?: boolean;
5
5
  min?: number;
6
- onHeightChange?: (height: number) => void;
7
6
  }
8
7
  export declare const ElasticHeight: FunctionComponent<ElasticHeightProps>;
9
8
  export {};
@@ -1,31 +1,22 @@
1
- "use client";
2
1
  import { t as e } from "../chunks/clsx.js";
3
- import t from "./hooks/useResizeObserver.js";
4
- import { useLayoutEffect as n, useRef as r, useState as i } from "react";
5
- import { jsx as a } from "react/jsx-runtime";
2
+ import { useRef as t } from "react";
3
+ import { jsx as n } from "react/jsx-runtime";
6
4
  //#region lib/ui/ElasticHeight.tsx
7
- var o = ({ className: o, children: s, innerClassName: c, isExpanded: l = !1, min: u = 0, ...d }) => {
8
- let f = r(null), [p, m] = i(0);
9
- return t({
10
- ref: f,
11
- onResize: () => {
12
- f.current && m(f.current?.offsetHeight);
13
- }
14
- }), n(() => {
15
- f.current && m(f.current.offsetHeight);
16
- }, [f]), /* @__PURE__ */ a("div", {
17
- ...d,
18
- className: e("overflow-hidden transition-all duration-500", o),
19
- "data-expanded": l,
20
- style: { height: l ? p : u },
21
- children: /* @__PURE__ */ a("div", {
22
- className: c,
23
- ref: f,
24
- children: s
5
+ var r = ({ className: r, children: i, innerClassName: a, isExpanded: o = !1, min: s = 0, ...c }) => {
6
+ let l = t(null);
7
+ return /* @__PURE__ */ n("div", {
8
+ ...c,
9
+ className: e("overflow-hidden transition-all duration-500 grid", "data-[expanded=true]:grid-rows-[1fr]", "data-[expanded=false]:grid-rows-[0fr]", r),
10
+ "data-expanded": o,
11
+ children: /* @__PURE__ */ n("div", {
12
+ style: { minHeight: s },
13
+ className: e("overflow-hidden", a),
14
+ ref: l,
15
+ children: i
25
16
  })
26
17
  });
27
18
  };
28
19
  //#endregion
29
- export { o as ElasticHeight };
20
+ export { r as ElasticHeight };
30
21
 
31
22
  //# sourceMappingURL=ElasticHeight.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElasticHeight.js","names":[],"sources":["../../lib/ui/ElasticHeight.tsx"],"sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport {\n type ComponentPropsWithoutRef,\n type FunctionComponent,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport useResizeObserver from './hooks/useResizeObserver';\n\ninterface ElasticHeightProps extends ComponentPropsWithoutRef<'div'> {\n innerClassName?: string;\n isExpanded?: boolean;\n min?: number;\n onHeightChange?: (height: number) => void;\n}\n\nexport const ElasticHeight: FunctionComponent<ElasticHeightProps> = ({\n className,\n children,\n innerClassName,\n isExpanded = false,\n min = 0,\n ...attrs\n}) => {\n const ref = useRef<HTMLDivElement>(null as any);\n const [max, setMax] = useState(0);\n\n useResizeObserver<HTMLDivElement>({\n ref: ref,\n onResize: () => {\n if (ref.current) {\n setMax(ref.current?.offsetHeight);\n }\n },\n });\n\n useLayoutEffect(() => {\n if (!ref.current) {\n return;\n }\n setMax(ref.current.offsetHeight);\n }, [ref]);\n\n return (\n <div\n {...attrs}\n className={clsx('overflow-hidden transition-all duration-500', className)}\n data-expanded={isExpanded}\n style={{ height: isExpanded ? max : min }}\n >\n <div className={innerClassName} ref={ref}>\n {children}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAmBA,IAAa,KAAwD,EACnE,cACA,aACA,mBACA,gBAAa,IACb,SAAM,GACN,GAAG,QACC;CACJ,IAAM,IAAM,EAAuB,KAAY,EACzC,CAAC,GAAK,KAAU,EAAS,EAAE;AAkBjC,QAhBA,EAAkC;EAC3B;EACL,gBAAgB;AACd,GAAI,EAAI,WACN,EAAO,EAAI,SAAS,aAAa;;EAGtC,CAAC,EAEF,QAAsB;AACf,IAAI,WAGT,EAAO,EAAI,QAAQ,aAAa;IAC/B,CAAC,EAAI,CAAC,EAGP,kBAAC,OAAD;EACE,GAAI;EACJ,WAAW,EAAK,+CAA+C,EAAU;EACzE,iBAAe;EACf,OAAO,EAAE,QAAQ,IAAa,IAAM,GAAK;YAEzC,kBAAC,OAAD;GAAK,WAAW;GAAqB;GAClC;GACG,CAAA;EACF,CAAA"}
1
+ {"version":3,"file":"ElasticHeight.js","names":[],"sources":["../../lib/ui/ElasticHeight.tsx"],"sourcesContent":["import clsx from 'clsx';\nimport { type ComponentPropsWithoutRef, type FunctionComponent, useRef } from 'react';\n\ninterface ElasticHeightProps extends ComponentPropsWithoutRef<'div'> {\n innerClassName?: string;\n isExpanded?: boolean;\n min?: number;\n}\n\nexport const ElasticHeight: FunctionComponent<ElasticHeightProps> = ({\n className,\n children,\n innerClassName,\n isExpanded = false,\n min = 0,\n ...attrs\n}) => {\n const ref = useRef<HTMLDivElement>(null as any);\n\n return (\n <div\n {...attrs}\n className={clsx(\n 'overflow-hidden transition-all duration-500 grid',\n 'data-[expanded=true]:grid-rows-[1fr]',\n 'data-[expanded=false]:grid-rows-[0fr]',\n className,\n )}\n data-expanded={isExpanded}\n >\n <div style={{ minHeight: min }} className={clsx('overflow-hidden', innerClassName)} ref={ref}>\n {children}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;AASA,IAAa,KAAwD,EACnE,cACA,aACA,mBACA,gBAAa,IACb,SAAM,GACN,GAAG,QACC;CACJ,IAAM,IAAM,EAAuB,KAAY;AAE/C,QACE,kBAAC,OAAD;EACE,GAAI;EACJ,WAAW,EACT,oDACA,wCACA,yCACA,EACD;EACD,iBAAe;YAEf,kBAAC,OAAD;GAAK,OAAO,EAAE,WAAW,GAAK;GAAE,WAAW,EAAK,mBAAmB,EAAe;GAAO;GACtF;GACG,CAAA;EACF,CAAA"}
package/ui/Frame.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ import { Card } from './cards/Card';
3
+ type FrameFormat = 'horizontal' | 'vertical';
4
+ export interface FrameProps extends Omit<ComponentPropsWithoutRef<typeof Card>, 'theme' | 'format' | 'children'> {
5
+ format?: FrameFormat;
6
+ src: string;
7
+ alt: string;
8
+ coverLink?: boolean;
9
+ buttonAriaLabel?: string;
10
+ title: string;
11
+ subtitle?: string;
12
+ children?: ReactNode;
13
+ }
14
+ export declare function Frame({ format, src, alt, coverLink, buttonAriaLabel, title, subtitle, children, className, ...cardProps }: FrameProps): import("react/jsx-runtime").JSX.Element;
15
+ export {};
package/ui/Frame.js ADDED
@@ -0,0 +1,39 @@
1
+ import { Button as e } from "./buttons/Button.js";
2
+ import { Card as t } from "./cards/Card.js";
3
+ import { CardBackground as n } from "./cards/CardBackground.js";
4
+ import { CardClickable as r } from "./cards/CardClickable.js";
5
+ import { HeadingGroup as i } from "./heading/HeadingGroup.js";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ //#region lib/ui/Frame.tsx
8
+ function s({ format: s = "horizontal", src: c, alt: l, coverLink: u = !0, buttonAriaLabel: d = "View details", title: f, subtitle: p, children: m, className: h, ...g }) {
9
+ return /* @__PURE__ */ a(t, {
10
+ theme: "frame",
11
+ format: s,
12
+ className: h,
13
+ ...g,
14
+ children: /* @__PURE__ */ o(n, {
15
+ src: c,
16
+ alt: l,
17
+ children: [m, /* @__PURE__ */ o(r, {
18
+ coverLink: u,
19
+ className: "w-full justify-between",
20
+ children: [/* @__PURE__ */ a(i, {
21
+ level: 2,
22
+ subtitle: p,
23
+ children: f
24
+ }), /* @__PURE__ */ a(e, {
25
+ color: "white",
26
+ theme: "outline",
27
+ variant: "circle",
28
+ icon: "ArrowDefaultRight",
29
+ "aria-label": d,
30
+ className: "pointer-events-auto shrink-0"
31
+ })]
32
+ })]
33
+ })
34
+ });
35
+ }
36
+ //#endregion
37
+ export { s as Frame };
38
+
39
+ //# sourceMappingURL=Frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Frame.js","names":[],"sources":["../../lib/ui/Frame.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\nimport { Card } from './cards/Card';\nimport { CardBackground } from './cards/CardBackground';\nimport { CardClickable } from './cards/CardClickable';\nimport { Button } from './buttons/Button';\nimport { HeadingGroup } from './heading/HeadingGroup';\n\ntype FrameFormat = 'horizontal' | 'vertical';\n\nexport interface FrameProps\n extends Omit<ComponentPropsWithoutRef<typeof Card>, 'theme' | 'format' | 'children'> {\n format?: FrameFormat;\n src: string;\n alt: string;\n coverLink?: boolean;\n buttonAriaLabel?: string;\n title: string;\n subtitle?: string;\n children?: ReactNode;\n}\n\nexport function Frame({\n format = 'horizontal',\n src,\n alt,\n coverLink = true,\n buttonAriaLabel = 'View details',\n title,\n subtitle,\n children,\n className,\n ...cardProps\n}: FrameProps) {\n return (\n <Card theme=\"frame\" format={format} className={className} {...cardProps}>\n <CardBackground src={src} alt={alt}>\n {children}\n <CardClickable coverLink={coverLink} className=\"w-full justify-between\">\n <HeadingGroup level={2} subtitle={subtitle}>\n {title}\n </HeadingGroup>\n <Button\n color=\"white\"\n theme=\"outline\"\n variant=\"circle\"\n icon=\"ArrowDefaultRight\"\n aria-label={buttonAriaLabel}\n className=\"pointer-events-auto shrink-0\"\n />\n </CardClickable>\n </CardBackground>\n </Card>\n );\n}\n"],"mappings":";;;;;;;AAqBA,SAAgB,EAAM,EACpB,YAAS,cACT,QACA,QACA,eAAY,IACZ,qBAAkB,gBAClB,UACA,aACA,aACA,cACA,GAAG,KACU;AACb,QACE,kBAAC,GAAD;EAAM,OAAM;EAAgB;EAAmB;EAAW,GAAI;YAC5D,kBAAC,GAAD;GAAqB;GAAU;aAA/B,CACG,GACD,kBAAC,GAAD;IAA0B;IAAW,WAAU;cAA/C,CACE,kBAAC,GAAD;KAAc,OAAO;KAAa;eAC/B;KACY,CAAA,EACf,kBAAC,GAAD;KACE,OAAM;KACN,OAAM;KACN,SAAQ;KACR,MAAK;KACL,cAAY;KACZ,WAAU;KACV,CAAA,CACY;MACD;;EACZ,CAAA"}
package/ui/Loader.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { FunctionComponent } from 'react';
2
- interface Props {
1
+ import { ComponentProps, FunctionComponent } from 'react';
2
+ import { Backdrop } from './Backdrop';
3
+ export interface LoaderProps {
3
4
  isVisible?: boolean;
4
5
  label?: string;
6
+ portalId?: ComponentProps<typeof Backdrop>['target'];
5
7
  }
6
- export declare const Loader: FunctionComponent<Props>;
7
- export {};
8
+ export declare const Loader: FunctionComponent<LoaderProps>;