@jbpark/ui-kit 5.3.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,8 +43,8 @@ const Switch = ({ className, classNames, size = "medium", defaultChecked, checke
43
43
  },
44
44
  ...props,
45
45
  children: hasChildren && /* @__PURE__ */ jsxs("span", {
46
- className: cn(`grid leading-none text-white transition-[margin] duration-200
47
- will-change-[margin]`, config.fontSize, checked ? config.marginChecked : config.marginUnchecked),
46
+ className: cn(`grid leading-none transition-[margin] duration-200
47
+ will-change-[margin]`, config.fontSize, checked ? [config.marginChecked, "text-primary-foreground"] : [config.marginUnchecked, "text-foreground"]),
48
48
  children: [/* @__PURE__ */ jsx("span", {
49
49
  className: cn("col-start-1 row-start-1 transition-opacity duration-200", checked ? "opacity-100" : "opacity-0"),
50
50
  children: checkedChildren
@@ -1 +1 @@
1
- {"version":3,"file":"switch.mjs","names":["switchComponent"],"sources":["../../../src/components/atoms/switch.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { switchComponent } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst { Switch: Core } = switchComponent;\n\nconst sizeConfig = {\n medium: {\n core: 'default' as const,\n track: 'h-8! w-12!',\n handle: 'size-6!',\n handleChecked:\n 'data-[state=unchecked]:left-0.5 data-[state=checked]:left-[calc(100%-26px)]',\n fontSize: 'text-xs',\n marginChecked: 'mr-7 ml-2',\n marginUnchecked: 'mr-2 ml-7',\n },\n small: {\n core: 'sm' as const,\n track: 'h-6! w-10!',\n handle: 'size-5!',\n handleChecked:\n 'data-[state=unchecked]:left-0.5 data-[state=checked]:left-[calc(100%-22px)]',\n fontSize: 'text-[10px]',\n marginChecked: 'mr-6 ml-1.5',\n marginUnchecked: 'mr-1.5 ml-6',\n },\n};\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'button'>,\n 'onChange'\n> {\n classNames?: {\n track?: string;\n handle?: string;\n };\n size?: 'small' | 'medium';\n defaultChecked?: boolean;\n checked?: boolean;\n disabled?: boolean;\n onChange?: (checked: boolean) => void;\n checkedChildren?: React.ReactNode;\n unCheckedChildren?: React.ReactNode;\n}\n\nconst Switch = ({\n className,\n classNames,\n size = 'medium',\n defaultChecked,\n checked: _checked,\n onChange: _onChange = () => {},\n checkedChildren,\n unCheckedChildren,\n ...props\n}: Props) => {\n const [checked, onChange] = useControllableState<boolean>({\n value: _checked,\n defaultValue: defaultChecked ?? false,\n onChange: _onChange,\n });\n\n const hasChildren = !!(checkedChildren || unCheckedChildren);\n const config = sizeConfig[size];\n\n return (\n <Core\n checked={checked}\n size={config.core}\n className={cn(\n 'relative',\n config.track,\n hasChildren && 'w-auto! overflow-hidden',\n className,\n classNames?.track,\n //\n )}\n handleClassName={cn(\n config.handle,\n '!absolute top-1/2 !-translate-y-1/2 !translate-x-0',\n 'transition-[left] duration-200 will-change-[left]',\n config.handleChecked,\n classNames?.handle,\n //\n )}\n onCheckedChange={checked => {\n onChange(checked);\n }}\n {...props}\n >\n {hasChildren && (\n <span\n className={cn(\n `grid leading-none text-white transition-[margin] duration-200\n will-change-[margin]`,\n config.fontSize,\n checked ? config.marginChecked : config.marginUnchecked,\n //\n )}\n >\n <span\n className={cn(\n 'col-start-1 row-start-1 transition-opacity duration-200',\n checked ? 'opacity-100' : 'opacity-0',\n )}\n >\n {checkedChildren}\n </span>\n <span\n className={cn(\n 'col-start-1 row-start-1 transition-opacity duration-200',\n checked ? 'opacity-0' : 'opacity-100',\n )}\n >\n {unCheckedChildren}\n </span>\n </span>\n )}\n </Core>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,QAAQ,SAASA;AAEzB,MAAM,aAAa;CACjB,QAAQ;EACN,MAAM;EACN,OAAO;EACP,QAAQ;EACR,eACE;EACF,UAAU;EACV,eAAe;EACf,iBAAiB;CACnB;CACA,OAAO;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,eACE;EACF,UAAU;EACV,eAAe;EACf,iBAAiB;CACnB;AACF;AAmBA,MAAM,UAAU,EACd,WACA,YACA,OAAO,UACP,gBACA,SAAS,UACT,UAAU,kBAAkB,CAAC,GAC7B,iBACA,mBACA,GAAG,YACQ;CACX,MAAM,CAAC,SAAS,YAAY,qBAA8B;EACxD,OAAO;EACP,cAAc,kBAAkB;EAChC,UAAU;CACZ,CAAC;CAED,MAAM,cAAc,CAAC,EAAE,mBAAmB;CAC1C,MAAM,SAAS,WAAW;CAE1B,OACE,oBAAC,MAAD;EACW;EACT,MAAM,OAAO;EACb,WAAW,GACT,YACA,OAAO,OACP,eAAe,2BACf,WACA,YAAY,KAEd;EACA,iBAAiB,GACf,OAAO,QACP,sDACA,qDACA,OAAO,eACP,YAAY,MAEd;EACA,kBAAiB,YAAW;GAC1B,SAAS,OAAO;EAClB;EACA,GAAI;EAEH,UAAA,eACC,qBAAC,QAAD;GACE,WAAW,GACT;mCAEA,OAAO,UACP,UAAU,OAAO,gBAAgB,OAAO,eAE1C;GAPF,UAAA,CASE,oBAAC,QAAD;IACE,WAAW,GACT,2DACA,UAAU,gBAAgB,WAC5B;IAEC,UAAA;GACG,CAAA,GACN,oBAAC,QAAD;IACE,WAAW,GACT,2DACA,UAAU,cAAc,aAC1B;IAEC,UAAA;GACG,CAAA,CACF;;CAEJ,CAAA;AAEV"}
1
+ {"version":3,"file":"switch.mjs","names":["switchComponent"],"sources":["../../../src/components/atoms/switch.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { switchComponent } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst { Switch: Core } = switchComponent;\n\nconst sizeConfig = {\n medium: {\n core: 'default' as const,\n track: 'h-8! w-12!',\n handle: 'size-6!',\n handleChecked:\n 'data-[state=unchecked]:left-0.5 data-[state=checked]:left-[calc(100%-26px)]',\n fontSize: 'text-xs',\n marginChecked: 'mr-7 ml-2',\n marginUnchecked: 'mr-2 ml-7',\n },\n small: {\n core: 'sm' as const,\n track: 'h-6! w-10!',\n handle: 'size-5!',\n handleChecked:\n 'data-[state=unchecked]:left-0.5 data-[state=checked]:left-[calc(100%-22px)]',\n fontSize: 'text-[10px]',\n marginChecked: 'mr-6 ml-1.5',\n marginUnchecked: 'mr-1.5 ml-6',\n },\n};\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'button'>,\n 'onChange'\n> {\n classNames?: {\n track?: string;\n handle?: string;\n };\n size?: 'small' | 'medium';\n defaultChecked?: boolean;\n checked?: boolean;\n disabled?: boolean;\n onChange?: (checked: boolean) => void;\n checkedChildren?: React.ReactNode;\n unCheckedChildren?: React.ReactNode;\n}\n\nconst Switch = ({\n className,\n classNames,\n size = 'medium',\n defaultChecked,\n checked: _checked,\n onChange: _onChange = () => {},\n checkedChildren,\n unCheckedChildren,\n ...props\n}: Props) => {\n const [checked, onChange] = useControllableState<boolean>({\n value: _checked,\n defaultValue: defaultChecked ?? false,\n onChange: _onChange,\n });\n\n const hasChildren = !!(checkedChildren || unCheckedChildren);\n const config = sizeConfig[size];\n\n return (\n <Core\n checked={checked}\n size={config.core}\n className={cn(\n 'relative',\n config.track,\n hasChildren && 'w-auto! overflow-hidden',\n className,\n classNames?.track,\n //\n )}\n handleClassName={cn(\n config.handle,\n '!absolute top-1/2 !-translate-y-1/2 !translate-x-0',\n 'transition-[left] duration-200 will-change-[left]',\n config.handleChecked,\n classNames?.handle,\n //\n )}\n onCheckedChange={checked => {\n onChange(checked);\n }}\n {...props}\n >\n {hasChildren && (\n <span\n className={cn(\n `grid leading-none transition-[margin] duration-200\n will-change-[margin]`,\n config.fontSize,\n checked\n ? [config.marginChecked, 'text-primary-foreground']\n : [config.marginUnchecked, 'text-foreground'],\n //\n )}\n >\n <span\n className={cn(\n 'col-start-1 row-start-1 transition-opacity duration-200',\n checked ? 'opacity-100' : 'opacity-0',\n )}\n >\n {checkedChildren}\n </span>\n <span\n className={cn(\n 'col-start-1 row-start-1 transition-opacity duration-200',\n checked ? 'opacity-0' : 'opacity-100',\n )}\n >\n {unCheckedChildren}\n </span>\n </span>\n )}\n </Core>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,QAAQ,SAASA;AAEzB,MAAM,aAAa;CACjB,QAAQ;EACN,MAAM;EACN,OAAO;EACP,QAAQ;EACR,eACE;EACF,UAAU;EACV,eAAe;EACf,iBAAiB;CACnB;CACA,OAAO;EACL,MAAM;EACN,OAAO;EACP,QAAQ;EACR,eACE;EACF,UAAU;EACV,eAAe;EACf,iBAAiB;CACnB;AACF;AAmBA,MAAM,UAAU,EACd,WACA,YACA,OAAO,UACP,gBACA,SAAS,UACT,UAAU,kBAAkB,CAAC,GAC7B,iBACA,mBACA,GAAG,YACQ;CACX,MAAM,CAAC,SAAS,YAAY,qBAA8B;EACxD,OAAO;EACP,cAAc,kBAAkB;EAChC,UAAU;CACZ,CAAC;CAED,MAAM,cAAc,CAAC,EAAE,mBAAmB;CAC1C,MAAM,SAAS,WAAW;CAE1B,OACE,oBAAC,MAAD;EACW;EACT,MAAM,OAAO;EACb,WAAW,GACT,YACA,OAAO,OACP,eAAe,2BACf,WACA,YAAY,KAEd;EACA,iBAAiB,GACf,OAAO,QACP,sDACA,qDACA,OAAO,eACP,YAAY,MAEd;EACA,kBAAiB,YAAW;GAC1B,SAAS,OAAO;EAClB;EACA,GAAI;EAEH,UAAA,eACC,qBAAC,QAAD;GACE,WAAW,GACT;mCAEA,OAAO,UACP,UACI,CAAC,OAAO,eAAe,yBAAyB,IAChD,CAAC,OAAO,iBAAiB,iBAAiB,CAEhD;GATF,UAAA,CAWE,oBAAC,QAAD;IACE,WAAW,GACT,2DACA,UAAU,gBAAgB,WAC5B;IAEC,UAAA;GACG,CAAA,GACN,oBAAC,QAAD;IACE,WAAW,GACT,2DACA,UAAU,cAAc,aAC1B;IAEC,UAAA;GACG,CAAA,CACF;;CAEJ,CAAA;AAEV"}
@@ -1 +1 @@
1
- {"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";UAOiB;EACf,MAAM,MAAM;EACZ;EACA;EACA;EACA;EACA,WAAW,MAAM;;UAGF,cACP,KAAK,MAAM,yCAAyC;EAC5D;;cAYI,SAAQ,OAAA,QAAA,OAAA,UAAA,OAAA,QAAA,cAAA,YAOX,0BAAK,IAAA"}
1
+ {"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";UASiB;EACf,MAAM,MAAM;EACZ;EACA;EACA;EACA;EACA,WAAW,MAAM;;UAGF,cACP,KAAK,MAAM,yCAAyC;EAC5D;;cAYI,SAAQ,OAAA,QAAA,OAAA,UAAA,OAAA,QAAA,cAAA,YAOX,0BAAK,IAAA"}
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import usePauseOnHover from "./use-pause-on-hover.mjs";
2
3
  import { useEffect, useRef, useState } from "react";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  import { useGSAP } from "@gsap/react";
@@ -10,7 +11,7 @@ const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = fa
10
11
  const containerRef = useRef(null);
11
12
  const tweenRef = useRef(null);
12
13
  const [width, setWidth] = useState(_width);
13
- const [pause, setPause] = useState(false);
14
+ const { pause, hoverEvents } = usePauseOnHover(pauseOnHover);
14
15
  const [repeatCount, setRepeatCount] = useState(autoFill ? typeof autoFill === "boolean" ? INITIAL_AUTO_FILL_GUESS : autoFill : 0);
15
16
  const [prevWidthProp, setPrevWidthProp] = useState(_width);
16
17
  const [prevAutoFill, setPrevAutoFill] = useState(autoFill);
@@ -23,14 +24,6 @@ const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = fa
23
24
  setRepeatCount(autoFill ? typeof autoFill === "boolean" ? INITIAL_AUTO_FILL_GUESS : autoFill : 0);
24
25
  }
25
26
  const isPaused = _pause || pause;
26
- const hoverEvents = pauseOnHover ? {
27
- onMouseEnter: () => {
28
- setPause(true);
29
- },
30
- onMouseLeave: () => {
31
- setPause(false);
32
- }
33
- } : {};
34
27
  useEffect(() => {
35
28
  if (!autoFill || !children || !itemRefs.current[0] || typeof width === "string") return;
36
29
  const itemWidth = itemRefs.current[0].offsetWidth;
@@ -1 +1 @@
1
- {"version":3,"file":"item.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useGSAP } from '@gsap/react';\nimport { gsap } from 'gsap';\n\nexport interface ItemProps {\n key?: React.Key;\n speed?: number;\n autoFill?: boolean | number;\n pause?: boolean;\n pauseOnHover?: boolean;\n children?: React.ReactNode;\n}\n\nexport interface Props\n extends Omit<React.ComponentPropsWithoutRef<'div'>, 'key'>, ItemProps {\n width: string | number;\n}\n\n// `autoFill={true}` (the default on `Marquees`) needs *some* repeat count\n// before the item can be measured and the real count computed — this is\n// only ever visible for that one render, but rendering 100 copies (200\n// with the 2x loop duplication) up front was needlessly heavy for the\n// common case. A modest guess still avoids visible gaps for typical\n// item/container width ratios while cutting the worst-case default\n// render by ~90%.\nconst INITIAL_AUTO_FILL_GUESS = 10;\n\nconst Item = ({\n width: _width,\n speed = 100,\n autoFill = false,\n pause: _pause = false,\n pauseOnHover = false,\n children,\n}: Props) => {\n const itemRefs = useRef<HTMLDivElement[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const tweenRef = useRef<gsap.core.Tween | null>(null);\n\n const [width, setWidth] = useState<string | number>(_width);\n const [pause, setPause] = useState(false);\n const [repeatCount, setRepeatCount] = useState(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n const [prevWidthProp, setPrevWidthProp] = useState(_width);\n const [prevAutoFill, setPrevAutoFill] = useState(autoFill);\n\n // Adjusted directly in render (React's \"adjust state during render\"\n // pattern) instead of an effect, so `width`/`repeatCount` re-sync with\n // the prop in the same render it changes rather than the render after.\n if (_width !== prevWidthProp) {\n setPrevWidthProp(_width);\n setWidth(_width);\n }\n\n if (autoFill !== prevAutoFill) {\n setPrevAutoFill(autoFill);\n setRepeatCount(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n }\n\n const isPaused = _pause || pause;\n\n const hoverEvents = pauseOnHover\n ? {\n onMouseEnter: () => {\n setPause(true);\n },\n onMouseLeave: () => {\n setPause(false);\n },\n }\n : {};\n\n useEffect(() => {\n if (\n !autoFill ||\n !children ||\n !itemRefs.current[0] ||\n typeof width === 'string'\n ) {\n return;\n }\n\n const itemWidth = itemRefs.current[0].offsetWidth;\n\n if (itemWidth >= width) {\n setWidth(itemWidth);\n setRepeatCount(0);\n return;\n }\n\n let totalWidth = 0;\n let repeatCount = 0;\n\n while (totalWidth < width) {\n totalWidth += itemWidth;\n repeatCount += 1;\n }\n\n setWidth(totalWidth);\n setRepeatCount(repeatCount - 1);\n }, [autoFill, width, children]);\n\n useGSAP(\n () => {\n if (!containerRef.current || typeof width === 'string') {\n return;\n }\n\n if (tweenRef.current) {\n tweenRef.current.kill();\n }\n\n tweenRef.current = gsap.fromTo(\n containerRef.current,\n { x: 0 },\n {\n x: -width,\n duration: width / speed,\n repeat: -1,\n ease: 'linear',\n },\n );\n\n return () => {\n tweenRef.current?.kill();\n };\n },\n {\n scope: containerRef,\n dependencies: [width, speed],\n },\n );\n\n useEffect(() => {\n if (!tweenRef.current) {\n return;\n }\n\n if (isPaused) {\n tweenRef.current.pause();\n } else {\n tweenRef.current.play();\n }\n }, [isPaused]);\n\n return (\n <div\n className=\"flex overflow-hidden\"\n {...hoverEvents}\n //\n >\n <div ref={containerRef} className=\"flex flex-nowrap\">\n {[...Array(2)].map((_, index) => (\n <div\n key={index}\n style={{ minWidth: width }}\n className=\"flex flex-nowrap\"\n >\n <div\n ref={el => {\n if (el) {\n itemRefs.current[index] = el;\n }\n }}\n >\n {children}\n </div>\n {[\n ...Array(typeof autoFill === 'number' ? autoFill : repeatCount),\n ].map((_, i) => (\n <div key={i}>{children}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Item;\n"],"mappings":";;;;;;AA4BA,MAAM,0BAA0B;AAEhC,MAAM,QAAQ,EACZ,OAAO,QACP,QAAQ,KACR,WAAW,OACX,OAAO,SAAS,OAChB,eAAe,OACf,eACW;CACX,MAAM,WAAW,OAAyB,CAAC,CAAC;CAC5C,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,WAAW,OAA+B,IAAI;CAEpD,MAAM,CAAC,OAAO,YAAY,SAA0B,MAAM;CAC1D,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CACxC,MAAM,CAAC,aAAa,kBAAkB,SACpC,WACI,OAAO,aAAa,YAClB,0BACA,WACF,CACN;CACA,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,cAAc,mBAAmB,SAAS,QAAQ;CAKzD,IAAI,WAAW,eAAe;EAC5B,iBAAiB,MAAM;EACvB,SAAS,MAAM;CACjB;CAEA,IAAI,aAAa,cAAc;EAC7B,gBAAgB,QAAQ;EACxB,eACE,WACI,OAAO,aAAa,YAClB,0BACA,WACF,CACN;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,MAAM,cAAc,eAChB;EACE,oBAAoB;GAClB,SAAS,IAAI;EACf;EACA,oBAAoB;GAClB,SAAS,KAAK;EAChB;CACF,IACA,CAAC;CAEL,gBAAgB;EACd,IACE,CAAC,YACD,CAAC,YACD,CAAC,SAAS,QAAQ,MAClB,OAAO,UAAU,UAEjB;EAGF,MAAM,YAAY,SAAS,QAAQ,EAAE,CAAC;EAEtC,IAAI,aAAa,OAAO;GACtB,SAAS,SAAS;GAClB,eAAe,CAAC;GAChB;EACF;EAEA,IAAI,aAAa;EACjB,IAAI,cAAc;EAElB,OAAO,aAAa,OAAO;GACzB,cAAc;GACd,eAAe;EACjB;EAEA,SAAS,UAAU;EACnB,eAAe,cAAc,CAAC;CAChC,GAAG;EAAC;EAAU;EAAO;CAAQ,CAAC;CAE9B,cACQ;EACJ,IAAI,CAAC,aAAa,WAAW,OAAO,UAAU,UAC5C;EAGF,IAAI,SAAS,SACX,SAAS,QAAQ,KAAK;EAGxB,SAAS,UAAU,KAAK,OACtB,aAAa,SACb,EAAE,GAAG,EAAE,GACP;GACE,GAAG,CAAC;GACJ,UAAU,QAAQ;GAClB,QAAQ;GACR,MAAM;EACR,CACF;EAEA,aAAa;GACX,SAAS,SAAS,KAAK;EACzB;CACF,GACA;EACE,OAAO;EACP,cAAc,CAAC,OAAO,KAAK;CAC7B,CACF;CAEA,gBAAgB;EACd,IAAI,CAAC,SAAS,SACZ;EAGF,IAAI,UACF,SAAS,QAAQ,MAAM;OAEvB,SAAS,QAAQ,KAAK;CAE1B,GAAG,CAAC,QAAQ,CAAC;CAEb,OACE,oBAAC,OAAD;EACE,WAAU;EACV,GAAI;EAGJ,UAAA,oBAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAC/B,UAAA,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,UACrB,qBAAC,OAAD;IAEE,OAAO,EAAE,UAAU,MAAM;IACzB,WAAU;IAHZ,UAAA,CAKE,oBAAC,OAAD;KACE,MAAK,OAAM;MACT,IAAI,IACF,SAAS,QAAQ,SAAS;KAE9B;KAEC;IACE,CAAA,GACJ,CACC,GAAG,MAAM,OAAO,aAAa,WAAW,WAAW,WAAW,CAChE,CAAC,CAAC,KAAK,GAAG,MACR,oBAAC,OAAD,EAAc,SAAc,GAAlB,CAAkB,CAC7B,CACE;GAlBE,GAAA,KAkBF,CACN;EACE,CAAA;CACF,CAAA;AAET"}
1
+ {"version":3,"file":"item.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useGSAP } from '@gsap/react';\nimport { gsap } from 'gsap';\n\nimport usePauseOnHover from './use-pause-on-hover';\n\nexport interface ItemProps {\n key?: React.Key;\n speed?: number;\n autoFill?: boolean | number;\n pause?: boolean;\n pauseOnHover?: boolean;\n children?: React.ReactNode;\n}\n\nexport interface Props\n extends Omit<React.ComponentPropsWithoutRef<'div'>, 'key'>, ItemProps {\n width: string | number;\n}\n\n// `autoFill={true}` (the default on `Marquees`) needs *some* repeat count\n// before the item can be measured and the real count computed — this is\n// only ever visible for that one render, but rendering 100 copies (200\n// with the 2x loop duplication) up front was needlessly heavy for the\n// common case. A modest guess still avoids visible gaps for typical\n// item/container width ratios while cutting the worst-case default\n// render by ~90%.\nconst INITIAL_AUTO_FILL_GUESS = 10;\n\nconst Item = ({\n width: _width,\n speed = 100,\n autoFill = false,\n pause: _pause = false,\n pauseOnHover = false,\n children,\n}: Props) => {\n const itemRefs = useRef<HTMLDivElement[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const tweenRef = useRef<gsap.core.Tween | null>(null);\n\n const [width, setWidth] = useState<string | number>(_width);\n const { pause, hoverEvents } = usePauseOnHover(pauseOnHover);\n const [repeatCount, setRepeatCount] = useState(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n const [prevWidthProp, setPrevWidthProp] = useState(_width);\n const [prevAutoFill, setPrevAutoFill] = useState(autoFill);\n\n // Adjusted directly in render (React's \"adjust state during render\"\n // pattern) instead of an effect, so `width`/`repeatCount` re-sync with\n // the prop in the same render it changes rather than the render after.\n if (_width !== prevWidthProp) {\n setPrevWidthProp(_width);\n setWidth(_width);\n }\n\n if (autoFill !== prevAutoFill) {\n setPrevAutoFill(autoFill);\n setRepeatCount(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n }\n\n const isPaused = _pause || pause;\n\n useEffect(() => {\n if (\n !autoFill ||\n !children ||\n !itemRefs.current[0] ||\n typeof width === 'string'\n ) {\n return;\n }\n\n const itemWidth = itemRefs.current[0].offsetWidth;\n\n if (itemWidth >= width) {\n setWidth(itemWidth);\n setRepeatCount(0);\n return;\n }\n\n let totalWidth = 0;\n let repeatCount = 0;\n\n while (totalWidth < width) {\n totalWidth += itemWidth;\n repeatCount += 1;\n }\n\n setWidth(totalWidth);\n setRepeatCount(repeatCount - 1);\n }, [autoFill, width, children]);\n\n useGSAP(\n () => {\n if (!containerRef.current || typeof width === 'string') {\n return;\n }\n\n if (tweenRef.current) {\n tweenRef.current.kill();\n }\n\n tweenRef.current = gsap.fromTo(\n containerRef.current,\n { x: 0 },\n {\n x: -width,\n duration: width / speed,\n repeat: -1,\n ease: 'linear',\n },\n );\n\n return () => {\n tweenRef.current?.kill();\n };\n },\n {\n scope: containerRef,\n dependencies: [width, speed],\n },\n );\n\n useEffect(() => {\n if (!tweenRef.current) {\n return;\n }\n\n if (isPaused) {\n tweenRef.current.pause();\n } else {\n tweenRef.current.play();\n }\n }, [isPaused]);\n\n return (\n <div\n className=\"flex overflow-hidden\"\n {...hoverEvents}\n //\n >\n <div ref={containerRef} className=\"flex flex-nowrap\">\n {[...Array(2)].map((_, index) => (\n <div\n key={index}\n style={{ minWidth: width }}\n className=\"flex flex-nowrap\"\n >\n <div\n ref={el => {\n if (el) {\n itemRefs.current[index] = el;\n }\n }}\n >\n {children}\n </div>\n {[\n ...Array(typeof autoFill === 'number' ? autoFill : repeatCount),\n ].map((_, i) => (\n <div key={i}>{children}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Item;\n"],"mappings":";;;;;;;AA8BA,MAAM,0BAA0B;AAEhC,MAAM,QAAQ,EACZ,OAAO,QACP,QAAQ,KACR,WAAW,OACX,OAAO,SAAS,OAChB,eAAe,OACf,eACW;CACX,MAAM,WAAW,OAAyB,CAAC,CAAC;CAC5C,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,WAAW,OAA+B,IAAI;CAEpD,MAAM,CAAC,OAAO,YAAY,SAA0B,MAAM;CAC1D,MAAM,EAAE,OAAO,gBAAgB,gBAAgB,YAAY;CAC3D,MAAM,CAAC,aAAa,kBAAkB,SACpC,WACI,OAAO,aAAa,YAClB,0BACA,WACF,CACN;CACA,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,cAAc,mBAAmB,SAAS,QAAQ;CAKzD,IAAI,WAAW,eAAe;EAC5B,iBAAiB,MAAM;EACvB,SAAS,MAAM;CACjB;CAEA,IAAI,aAAa,cAAc;EAC7B,gBAAgB,QAAQ;EACxB,eACE,WACI,OAAO,aAAa,YAClB,0BACA,WACF,CACN;CACF;CAEA,MAAM,WAAW,UAAU;CAE3B,gBAAgB;EACd,IACE,CAAC,YACD,CAAC,YACD,CAAC,SAAS,QAAQ,MAClB,OAAO,UAAU,UAEjB;EAGF,MAAM,YAAY,SAAS,QAAQ,EAAE,CAAC;EAEtC,IAAI,aAAa,OAAO;GACtB,SAAS,SAAS;GAClB,eAAe,CAAC;GAChB;EACF;EAEA,IAAI,aAAa;EACjB,IAAI,cAAc;EAElB,OAAO,aAAa,OAAO;GACzB,cAAc;GACd,eAAe;EACjB;EAEA,SAAS,UAAU;EACnB,eAAe,cAAc,CAAC;CAChC,GAAG;EAAC;EAAU;EAAO;CAAQ,CAAC;CAE9B,cACQ;EACJ,IAAI,CAAC,aAAa,WAAW,OAAO,UAAU,UAC5C;EAGF,IAAI,SAAS,SACX,SAAS,QAAQ,KAAK;EAGxB,SAAS,UAAU,KAAK,OACtB,aAAa,SACb,EAAE,GAAG,EAAE,GACP;GACE,GAAG,CAAC;GACJ,UAAU,QAAQ;GAClB,QAAQ;GACR,MAAM;EACR,CACF;EAEA,aAAa;GACX,SAAS,SAAS,KAAK;EACzB;CACF,GACA;EACE,OAAO;EACP,cAAc,CAAC,OAAO,KAAK;CAC7B,CACF;CAEA,gBAAgB;EACd,IAAI,CAAC,SAAS,SACZ;EAGF,IAAI,UACF,SAAS,QAAQ,MAAM;OAEvB,SAAS,QAAQ,KAAK;CAE1B,GAAG,CAAC,QAAQ,CAAC;CAEb,OACE,oBAAC,OAAD;EACE,WAAU;EACV,GAAI;EAGJ,UAAA,oBAAC,OAAD;GAAK,KAAK;GAAc,WAAU;GAC/B,UAAA,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,UACrB,qBAAC,OAAD;IAEE,OAAO,EAAE,UAAU,MAAM;IACzB,WAAU;IAHZ,UAAA,CAKE,oBAAC,OAAD;KACE,MAAK,OAAM;MACT,IAAI,IACF,SAAS,QAAQ,SAAS;KAE9B;KAEC;IACE,CAAA,GACJ,CACC,GAAG,MAAM,OAAO,aAAa,WAAW,WAAW,WAAW,CAChE,CAAC,CAAC,KAAK,GAAG,MACR,oBAAC,OAAD,EAAc,SAAc,GAAlB,CAAkB,CAC7B,CACE;GAlBE,GAAA,KAkBF,CACN;EACE,CAAA;CACF,CAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"marquees.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/marquees.tsx"],"mappings":";;UAUiB,cAAc,MAAM;EACnC;EACA;EACA;EACA,QAAQ;;cAGJ,aAAY,WAAA,OAAA,OAAA,cAAA,aAAA,SAOf,0BAAK,IAAA"}
1
+ {"version":3,"file":"marquees.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/marquees.tsx"],"mappings":";;UAeiB,cAAc,MAAM;EACnC;EACA;EACA;EACA,QAAQ;;cAGJ,aAAY,WAAA,OAAA,OAAA,cAAA,aAAA,SAOf,0BAAK,IAAA"}
@@ -1,29 +1,19 @@
1
1
  "use client";
2
2
  import { cn } from "../../../utils.mjs";
3
+ import usePauseOnHover from "./use-pause-on-hover.mjs";
3
4
  import Item from "./item.mjs";
4
5
  import { useEffect, useRef, useState } from "react";
5
6
  import { jsx } from "react/jsx-runtime";
6
- import { useResponsiveSize, useThrottle } from "@jbpark/use-hooks";
7
+ import { useMergedRef, useResponsiveSize, useThrottledValue } from "@jbpark/use-hooks";
7
8
  //#region src/components/molecules/marquees/marquees.tsx
8
9
  const Marquees = ({ className, items, speed, pauseOnHover = true, autoFill = true, ...props }) => {
9
10
  const [width, setWidth] = useState("100vw");
10
11
  const [padding, setPadding] = useState(0);
11
- const [pause, setPause] = useState(false);
12
- const throttledWidth = useThrottle(width, 200);
12
+ const { pause, hoverEvents } = usePauseOnHover(pauseOnHover);
13
+ const throttledWidth = useThrottledValue(width, 200);
13
14
  const { size, ref: responsiveRef } = useResponsiveSize();
14
15
  const containerRef = useRef(null);
15
- const setContainerRef = (node) => {
16
- containerRef.current = node;
17
- responsiveRef(node);
18
- };
19
- const hoverEvents = pauseOnHover ? {
20
- onMouseEnter: () => {
21
- setPause(true);
22
- },
23
- onMouseLeave: () => {
24
- setPause(false);
25
- }
26
- } : {};
16
+ const setContainerRef = useMergedRef(containerRef, responsiveRef);
27
17
  useEffect(() => {
28
18
  if (!size.width || !containerRef.current) return;
29
19
  const computedStyle = getComputedStyle(containerRef.current);
@@ -1 +1 @@
1
- {"version":3,"file":"marquees.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/marquees.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useResponsiveSize, useThrottle } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Item, { type ItemProps } from './item';\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n speed?: number;\n autoFill?: boolean | number;\n pauseOnHover?: boolean;\n items?: ItemProps[];\n}\n\nconst Marquees = ({\n className,\n items,\n speed,\n pauseOnHover = true,\n autoFill = true,\n ...props\n}: Props) => {\n const [width, setWidth] = useState<string | number>(\n '100vw',\n //\n );\n const [padding, setPadding] = useState(0);\n const [pause, setPause] = useState(false);\n\n const throttledWidth = useThrottle(width, 200);\n\n const { size, ref: responsiveRef } = useResponsiveSize<HTMLDivElement>();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const setContainerRef = (node: HTMLDivElement | null) => {\n containerRef.current = node;\n responsiveRef(node);\n };\n const hoverEvents = pauseOnHover\n ? {\n onMouseEnter: () => {\n setPause(true);\n },\n onMouseLeave: () => {\n setPause(false);\n },\n }\n : {};\n\n useEffect(() => {\n if (!size.width || !containerRef.current) {\n return;\n }\n\n const computedStyle = getComputedStyle(containerRef.current);\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0;\n\n setPadding(paddingLeft + paddingRight);\n\n setWidth(size.width);\n }, [size]);\n\n return (\n <div\n ref={setContainerRef}\n className={cn(\n className,\n //\n )}\n {...hoverEvents}\n {...props}\n >\n <div\n className={cn(\n 'flex flex-col gap-y-5',\n 'overflow-hidden',\n 'whitespace-nowrap',\n 'bg-inherit',\n //\n )}\n style={{\n width:\n typeof throttledWidth === 'number'\n ? throttledWidth - padding\n : throttledWidth,\n }}\n >\n {items?.map(({ children, key: itemKey, ...item }: ItemProps, key) => (\n <Item\n key={itemKey || key}\n width={throttledWidth}\n pause={pause}\n speed={speed}\n autoFill={autoFill}\n {...item}\n >\n {children}\n </Item>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Marquees;\n"],"mappings":";;;;;;;AAiBA,MAAM,YAAY,EAChB,WACA,OACA,OACA,eAAe,MACf,WAAW,MACX,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,SACxB,OAEF;CACA,MAAM,CAAC,SAAS,cAAc,SAAS,CAAC;CACxC,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CAExC,MAAM,iBAAiB,YAAY,OAAO,GAAG;CAE7C,MAAM,EAAE,MAAM,KAAK,kBAAkB,kBAAkC;CACvE,MAAM,eAAe,OAA8B,IAAI;CACvD,MAAM,mBAAmB,SAAgC;EACvD,aAAa,UAAU;EACvB,cAAc,IAAI;CACpB;CACA,MAAM,cAAc,eAChB;EACE,oBAAoB;GAClB,SAAS,IAAI;EACf;EACA,oBAAoB;GAClB,SAAS,KAAK;EAChB;CACF,IACA,CAAC;CAEL,gBAAgB;EACd,IAAI,CAAC,KAAK,SAAS,CAAC,aAAa,SAC/B;EAGF,MAAM,gBAAgB,iBAAiB,aAAa,OAAO;EAC3D,MAAM,cAAc,WAAW,cAAc,WAAW,KAAK;EAC7D,MAAM,eAAe,WAAW,cAAc,YAAY,KAAK;EAE/D,WAAW,cAAc,YAAY;EAErC,SAAS,KAAK,KAAK;CACrB,GAAG,CAAC,IAAI,CAAC;CAET,OACE,oBAAC,OAAD;EACE,KAAK;EACL,WAAW,GACT,SAEF;EACA,GAAI;EACJ,GAAI;EAEJ,UAAA,oBAAC,OAAD;GACE,WAAW,GACT,yBACA,mBACA,qBACA,YAEF;GACA,OAAO,EACL,OACE,OAAO,mBAAmB,WACtB,iBAAiB,UACjB,eACR;GAEC,UAAA,OAAO,KAAK,EAAE,UAAU,KAAK,SAAS,GAAG,QAAmB,QAC3D,oBAAC,MAAD;IAEE,OAAO;IACA;IACA;IACG;IACV,GAAI;IAEH;GACG,GARC,WAAW,GAQZ,CACP;EACE,CAAA;CACF,CAAA;AAET"}
1
+ {"version":3,"file":"marquees.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/marquees.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport {\n useMergedRef,\n useResponsiveSize,\n useThrottledValue,\n} from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Item, { type ItemProps } from './item';\nimport usePauseOnHover from './use-pause-on-hover';\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n speed?: number;\n autoFill?: boolean | number;\n pauseOnHover?: boolean;\n items?: ItemProps[];\n}\n\nconst Marquees = ({\n className,\n items,\n speed,\n pauseOnHover = true,\n autoFill = true,\n ...props\n}: Props) => {\n const [width, setWidth] = useState<string | number>(\n '100vw',\n //\n );\n const [padding, setPadding] = useState(0);\n const { pause, hoverEvents } = usePauseOnHover(pauseOnHover);\n\n const throttledWidth = useThrottledValue(width, 200);\n\n const { size, ref: responsiveRef } = useResponsiveSize<HTMLDivElement>();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const setContainerRef = useMergedRef(containerRef, responsiveRef);\n\n useEffect(() => {\n if (!size.width || !containerRef.current) {\n return;\n }\n\n const computedStyle = getComputedStyle(containerRef.current);\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0;\n\n setPadding(paddingLeft + paddingRight);\n\n setWidth(size.width);\n }, [size]);\n\n return (\n <div\n ref={setContainerRef}\n className={cn(\n className,\n //\n )}\n {...hoverEvents}\n {...props}\n >\n <div\n className={cn(\n 'flex flex-col gap-y-5',\n 'overflow-hidden',\n 'whitespace-nowrap',\n 'bg-inherit',\n //\n )}\n style={{\n width:\n typeof throttledWidth === 'number'\n ? throttledWidth - padding\n : throttledWidth,\n }}\n >\n {items?.map(({ children, key: itemKey, ...item }: ItemProps, key) => (\n <Item\n key={itemKey || key}\n width={throttledWidth}\n pause={pause}\n speed={speed}\n autoFill={autoFill}\n {...item}\n >\n {children}\n </Item>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Marquees;\n"],"mappings":";;;;;;;;AAsBA,MAAM,YAAY,EAChB,WACA,OACA,OACA,eAAe,MACf,WAAW,MACX,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,SACxB,OAEF;CACA,MAAM,CAAC,SAAS,cAAc,SAAS,CAAC;CACxC,MAAM,EAAE,OAAO,gBAAgB,gBAAgB,YAAY;CAE3D,MAAM,iBAAiB,kBAAkB,OAAO,GAAG;CAEnD,MAAM,EAAE,MAAM,KAAK,kBAAkB,kBAAkC;CACvE,MAAM,eAAe,OAA8B,IAAI;CACvD,MAAM,kBAAkB,aAAa,cAAc,aAAa;CAEhE,gBAAgB;EACd,IAAI,CAAC,KAAK,SAAS,CAAC,aAAa,SAC/B;EAGF,MAAM,gBAAgB,iBAAiB,aAAa,OAAO;EAC3D,MAAM,cAAc,WAAW,cAAc,WAAW,KAAK;EAC7D,MAAM,eAAe,WAAW,cAAc,YAAY,KAAK;EAE/D,WAAW,cAAc,YAAY;EAErC,SAAS,KAAK,KAAK;CACrB,GAAG,CAAC,IAAI,CAAC;CAET,OACE,oBAAC,OAAD;EACE,KAAK;EACL,WAAW,GACT,SAEF;EACA,GAAI;EACJ,GAAI;EAEJ,UAAA,oBAAC,OAAD;GACE,WAAW,GACT,yBACA,mBACA,qBACA,YAEF;GACA,OAAO,EACL,OACE,OAAO,mBAAmB,WACtB,iBAAiB,UACjB,eACR;GAEC,UAAA,OAAO,KAAK,EAAE,UAAU,KAAK,SAAS,GAAG,QAAmB,QAC3D,oBAAC,MAAD;IAEE,OAAO;IACA;IACA;IACG;IACV,GAAI;IAEH;GACG,GARC,WAAW,GAQZ,CACP;EACE,CAAA;CACF,CAAA;AAET"}
@@ -0,0 +1,26 @@
1
+ import { useState } from "react";
2
+ //#region src/components/molecules/marquees/use-pause-on-hover.ts
3
+ const usePauseOnHover = (enabled) => {
4
+ const [pause, setPause] = useState(false);
5
+ return {
6
+ pause,
7
+ hoverEvents: enabled ? {
8
+ onMouseEnter: () => {
9
+ setPause(true);
10
+ },
11
+ onMouseLeave: () => {
12
+ setPause(false);
13
+ },
14
+ onFocus: () => {
15
+ setPause(true);
16
+ },
17
+ onBlur: () => {
18
+ setPause(false);
19
+ }
20
+ } : {}
21
+ };
22
+ };
23
+ //#endregion
24
+ export { usePauseOnHover as default };
25
+
26
+ //# sourceMappingURL=use-pause-on-hover.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-pause-on-hover.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/use-pause-on-hover.ts"],"sourcesContent":["import { useState } from 'react';\n\n// Pausing on hover alone leaves keyboard users with no way to stop the\n// marquee, so focus/blur (which bubble from any interactive child) pause it\n// the same way hover does.\nconst usePauseOnHover = (enabled: boolean) => {\n const [pause, setPause] = useState(false);\n\n const hoverEvents = enabled\n ? {\n onMouseEnter: () => {\n setPause(true);\n },\n onMouseLeave: () => {\n setPause(false);\n },\n onFocus: () => {\n setPause(true);\n },\n onBlur: () => {\n setPause(false);\n },\n }\n : {};\n\n return { pause, hoverEvents };\n};\n\nexport default usePauseOnHover;\n"],"mappings":";;AAKA,MAAM,mBAAmB,YAAqB;CAC5C,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK;CAmBxC,OAAO;EAAE;EAAO,aAjBI,UAChB;GACE,oBAAoB;IAClB,SAAS,IAAI;GACf;GACA,oBAAoB;IAClB,SAAS,KAAK;GAChB;GACA,eAAe;IACb,SAAS,IAAI;GACf;GACA,cAAc;IACZ,SAAS,KAAK;GAChB;EACF,IACA,CAAC;CAEuB;AAC9B"}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { ConfigSnapshotProvider, getRootConfigValue } from "../../providers/config/registry.mjs";
3
- import { useEffect, useState } from "react";
3
+ import { useCallback, useSyncExternalStore } from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import { v4 } from "uuid";
6
6
  import { createRoot } from "react-dom/client";
@@ -34,15 +34,15 @@ function createImperativeStack({ createRootElement, StackItem }) {
34
34
  return rootEl;
35
35
  };
36
36
  const StackRenderer = ({ container }) => {
37
- const [, forceUpdate] = useState({});
38
- useEffect(() => {
37
+ const subscribe = useCallback((onStoreChange) => {
39
38
  const state = getContainerState(container);
40
- state.update = () => forceUpdate({});
39
+ state.update = onStoreChange;
41
40
  return () => {
42
41
  state.update = null;
43
42
  };
44
43
  }, [container]);
45
- const { stack } = getContainerState(container);
44
+ const getSnapshot = useCallback(() => getContainerState(container).stack, [container]);
45
+ const stack = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
46
46
  return /* @__PURE__ */ jsx(ConfigSnapshotProvider, { children: stack.map(({ id, ...props }) => /* @__PURE__ */ jsx(StackItem, {
47
47
  id,
48
48
  ...props
@@ -59,10 +59,10 @@ function createImperativeStack({ createRootElement, StackItem }) {
59
59
  }
60
60
  const state = getContainerState(targetContainer);
61
61
  const id = props.id || v4();
62
- state.stack.push({
62
+ state.stack = [...state.stack, {
63
63
  ...props,
64
64
  id
65
- });
65
+ }];
66
66
  state.update?.();
67
67
  return id;
68
68
  };
@@ -1 +1 @@
1
- {"version":3,"file":"imperative-stack.mjs","names":["uuid"],"sources":["../../../src/components/organisms/imperative-stack.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { Root, createRoot } from 'react-dom/client';\n\nimport { v4 as uuid } from 'uuid';\n\nimport { ConfigSnapshotProvider, getRootConfigValue } from '@repo/ui/providers';\n\n// Shared machinery behind Modal.info/success/error/warning/confirm and\n// Toast.info/success/error/warning — both used to independently\n// reimplement ~120 near-identical lines of this (container-scoped stack,\n// a React root per container, imperative render/destroy). The only parts\n// that actually differ between the two are the DOM node their stack\n// mounts into (position/ARIA) and which component renders each stack\n// entry — everything else here is generic over that.\n\nexport const isBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n\ntype ContainerState<TProps> = {\n stack: (TProps & { id: string })[];\n update: (() => void) | null;\n};\n\nexport interface ImperativeStack<\n TProps extends { id?: string; container?: HTMLElement },\n> {\n render: (props: TProps) => string | undefined;\n destroy: (id?: string) => void;\n getRootElement: (container?: HTMLElement) => HTMLElement | null;\n}\n\nexport interface ImperativeStackOptions<\n TProps extends { id?: string; container?: HTMLElement },\n> {\n /** Creates the DOM node this stack's React root mounts into — not yet\n * attached to the document; the factory appends it to the target\n * container itself. Called once per distinct container. */\n createRootElement: () => HTMLElement;\n /** Renders one stack entry — typically each caller's \"Static<Thing>\"\n * component, which owns its own createPortal(..., getRootElement()). */\n StackItem: React.ComponentType<TProps & { id: string }>;\n}\n\nexport function createImperativeStack<\n TProps extends { id?: string; container?: HTMLElement },\n>({\n createRootElement,\n StackItem,\n}: ImperativeStackOptions<TProps>): ImperativeStack<TProps> {\n const containerStates = new Map<HTMLElement, ContainerState<TProps>>();\n const rootElements = new WeakMap<HTMLElement, HTMLElement>();\n const reactRoots = new Map<HTMLElement, Root>();\n\n const getContainerState = (\n container: HTMLElement,\n ): ContainerState<TProps> => {\n let state = containerStates.get(container);\n\n if (!state) {\n state = { stack: [], update: null };\n containerStates.set(container, state);\n }\n\n return state;\n };\n\n // Shared by `render` and `getRootElement` so both agree on the same\n // target container whenever the caller doesn't pass one explicitly — the\n // stack's React root (created once, in `render`) and the DOM node a\n // `StackItem` (e.g. StaticToast) later portals into (calling\n // `getRootElement` again with the same, possibly-undefined `container`)\n // would otherwise resolve two different containers here, splitting the\n // React tree (correctly under the root Config, via ConfigSnapshotProvider\n // above) from the actual visible DOM (silently back under `document.body`,\n // outside the Config's themed wrapper — undoing this fix's whole point).\n const resolveContainer = (container?: HTMLElement): HTMLElement =>\n container || getRootConfigValue()?.getContainer() || document.body;\n\n const getRootElement = (container?: HTMLElement): HTMLElement | null => {\n if (!isBrowser) {\n return null;\n }\n\n const targetContainer = resolveContainer(container);\n let rootEl = rootElements.get(targetContainer);\n\n if (!rootEl) {\n rootEl = createRootElement();\n targetContainer.appendChild(rootEl);\n rootElements.set(targetContainer, rootEl);\n }\n\n return rootEl;\n };\n\n const StackRenderer = ({ container }: { container: HTMLElement }) => {\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n const state = getContainerState(container);\n state.update = () => forceUpdate({});\n return () => {\n state.update = null;\n };\n }, [container]);\n\n const { stack } = getContainerState(container);\n\n return (\n <ConfigSnapshotProvider>\n {stack.map(({ id, ...props }) => (\n <StackItem key={id} id={id} {...(props as TProps)} />\n ))}\n </ConfigSnapshotProvider>\n );\n };\n\n const render = (props: TProps): string | undefined => {\n if (!isBrowser) {\n return;\n }\n\n // An explicit `container` prop always wins (it may be chosen for\n // layout reasons unrelated to theming); otherwise mount into the root\n // Config's own themed wrapper element (if one renders — see\n // `needsWrapper` in config.tsx) so CSS custom properties and the\n // `.dark` class cascade to this stack via normal DOM inheritance, not\n // just `document.body` sitting as an unthemed sibling of it.\n const targetContainer = resolveContainer(props.container);\n const rootElement = getRootElement(targetContainer)!;\n\n if (!reactRoots.has(targetContainer)) {\n const root = createRoot(rootElement);\n reactRoots.set(targetContainer, root);\n root.render(<StackRenderer container={targetContainer} />);\n }\n\n const state = getContainerState(targetContainer);\n const id = props.id || uuid();\n state.stack.push({ ...props, id });\n state.update?.();\n\n return id;\n };\n\n const destroy = (id?: string) => {\n if (!id) {\n containerStates.forEach(state => {\n state.stack = [];\n state.update?.();\n });\n reactRoots.forEach((root, container) => {\n root.unmount();\n rootElements.get(container)?.remove();\n rootElements.delete(container);\n });\n reactRoots.clear();\n containerStates.clear();\n return;\n }\n\n containerStates.forEach((state, container) => {\n if (!state.stack.some(item => item.id === id)) {\n return;\n }\n\n state.stack = state.stack.filter(item => item.id !== id);\n state.update?.();\n\n if (!state.stack.length) {\n reactRoots.get(container)?.unmount();\n reactRoots.delete(container);\n containerStates.delete(container);\n rootElements.get(container)?.remove();\n rootElements.delete(container);\n }\n });\n };\n\n return { render, destroy, getRootElement };\n}\n"],"mappings":";;;;;;;AAiBA,MAAa,YACX,OAAO,WAAW,eAAe,OAAO,aAAa;AA2BvD,SAAgB,sBAEd,EACA,mBACA,aAC0D;CAC1D,MAAM,kCAAkB,IAAI,IAAyC;CACrE,MAAM,+BAAe,IAAI,QAAkC;CAC3D,MAAM,6BAAa,IAAI,IAAuB;CAE9C,MAAM,qBACJ,cAC2B;EAC3B,IAAI,QAAQ,gBAAgB,IAAI,SAAS;EAEzC,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,OAAO,CAAC;IAAG,QAAQ;GAAK;GAClC,gBAAgB,IAAI,WAAW,KAAK;EACtC;EAEA,OAAO;CACT;CAWA,MAAM,oBAAoB,cACxB,aAAa,mBAAmB,CAAC,EAAE,aAAa,KAAK,SAAS;CAEhE,MAAM,kBAAkB,cAAgD;EACtE,IAAI,CAAC,WACH,OAAO;EAGT,MAAM,kBAAkB,iBAAiB,SAAS;EAClD,IAAI,SAAS,aAAa,IAAI,eAAe;EAE7C,IAAI,CAAC,QAAQ;GACX,SAAS,kBAAkB;GAC3B,gBAAgB,YAAY,MAAM;GAClC,aAAa,IAAI,iBAAiB,MAAM;EAC1C;EAEA,OAAO;CACT;CAEA,MAAM,iBAAiB,EAAE,gBAA4C;EACnE,MAAM,GAAG,eAAe,SAAS,CAAC,CAAC;EAEnC,gBAAgB;GACd,MAAM,QAAQ,kBAAkB,SAAS;GACzC,MAAM,eAAe,YAAY,CAAC,CAAC;GACnC,aAAa;IACX,MAAM,SAAS;GACjB;EACF,GAAG,CAAC,SAAS,CAAC;EAEd,MAAM,EAAE,UAAU,kBAAkB,SAAS;EAE7C,OACE,oBAAC,wBAAD,EAAA,UACG,MAAM,KAAK,EAAE,IAAI,GAAG,YACnB,oBAAC,WAAD;GAAwB;GAAI,GAAK;EAAmB,GAApC,EAAoC,CACrD,EACqB,CAAA;CAE5B;CAEA,MAAM,UAAU,UAAsC;EACpD,IAAI,CAAC,WACH;EASF,MAAM,kBAAkB,iBAAiB,MAAM,SAAS;EACxD,MAAM,cAAc,eAAe,eAAe;EAElD,IAAI,CAAC,WAAW,IAAI,eAAe,GAAG;GACpC,MAAM,OAAO,WAAW,WAAW;GACnC,WAAW,IAAI,iBAAiB,IAAI;GACpC,KAAK,OAAO,oBAAC,eAAD,EAAe,WAAW,gBAAkB,CAAA,CAAC;EAC3D;EAEA,MAAM,QAAQ,kBAAkB,eAAe;EAC/C,MAAM,KAAK,MAAM,MAAMA,GAAK;EAC5B,MAAM,MAAM,KAAK;GAAE,GAAG;GAAO;EAAG,CAAC;EACjC,MAAM,SAAS;EAEf,OAAO;CACT;CAEA,MAAM,WAAW,OAAgB;EAC/B,IAAI,CAAC,IAAI;GACP,gBAAgB,SAAQ,UAAS;IAC/B,MAAM,QAAQ,CAAC;IACf,MAAM,SAAS;GACjB,CAAC;GACD,WAAW,SAAS,MAAM,cAAc;IACtC,KAAK,QAAQ;IACb,aAAa,IAAI,SAAS,CAAC,EAAE,OAAO;IACpC,aAAa,OAAO,SAAS;GAC/B,CAAC;GACD,WAAW,MAAM;GACjB,gBAAgB,MAAM;GACtB;EACF;EAEA,gBAAgB,SAAS,OAAO,cAAc;GAC5C,IAAI,CAAC,MAAM,MAAM,MAAK,SAAQ,KAAK,OAAO,EAAE,GAC1C;GAGF,MAAM,QAAQ,MAAM,MAAM,QAAO,SAAQ,KAAK,OAAO,EAAE;GACvD,MAAM,SAAS;GAEf,IAAI,CAAC,MAAM,MAAM,QAAQ;IACvB,WAAW,IAAI,SAAS,CAAC,EAAE,QAAQ;IACnC,WAAW,OAAO,SAAS;IAC3B,gBAAgB,OAAO,SAAS;IAChC,aAAa,IAAI,SAAS,CAAC,EAAE,OAAO;IACpC,aAAa,OAAO,SAAS;GAC/B;EACF,CAAC;CACH;CAEA,OAAO;EAAE;EAAQ;EAAS;CAAe;AAC3C"}
1
+ {"version":3,"file":"imperative-stack.mjs","names":["uuid"],"sources":["../../../src/components/organisms/imperative-stack.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { Root, createRoot } from 'react-dom/client';\n\nimport { v4 as uuid } from 'uuid';\n\nimport { ConfigSnapshotProvider, getRootConfigValue } from '@repo/ui/providers';\n\n// Shared machinery behind Modal.info/success/error/warning/confirm and\n// Toast.info/success/error/warning — both used to independently\n// reimplement ~120 near-identical lines of this (container-scoped stack,\n// a React root per container, imperative render/destroy). The only parts\n// that actually differ between the two are the DOM node their stack\n// mounts into (position/ARIA) and which component renders each stack\n// entry — everything else here is generic over that.\n\nexport const isBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n\ntype ContainerState<TProps> = {\n stack: (TProps & { id: string })[];\n update: (() => void) | null;\n};\n\nexport interface ImperativeStack<\n TProps extends { id?: string; container?: HTMLElement },\n> {\n render: (props: TProps) => string | undefined;\n destroy: (id?: string) => void;\n getRootElement: (container?: HTMLElement) => HTMLElement | null;\n}\n\nexport interface ImperativeStackOptions<\n TProps extends { id?: string; container?: HTMLElement },\n> {\n /** Creates the DOM node this stack's React root mounts into — not yet\n * attached to the document; the factory appends it to the target\n * container itself. Called once per distinct container. */\n createRootElement: () => HTMLElement;\n /** Renders one stack entry — typically each caller's \"Static<Thing>\"\n * component, which owns its own createPortal(..., getRootElement()). */\n StackItem: React.ComponentType<TProps & { id: string }>;\n}\n\nexport function createImperativeStack<\n TProps extends { id?: string; container?: HTMLElement },\n>({\n createRootElement,\n StackItem,\n}: ImperativeStackOptions<TProps>): ImperativeStack<TProps> {\n const containerStates = new Map<HTMLElement, ContainerState<TProps>>();\n const rootElements = new WeakMap<HTMLElement, HTMLElement>();\n const reactRoots = new Map<HTMLElement, Root>();\n\n const getContainerState = (\n container: HTMLElement,\n ): ContainerState<TProps> => {\n let state = containerStates.get(container);\n\n if (!state) {\n state = { stack: [], update: null };\n containerStates.set(container, state);\n }\n\n return state;\n };\n\n // Shared by `render` and `getRootElement` so both agree on the same\n // target container whenever the caller doesn't pass one explicitly — the\n // stack's React root (created once, in `render`) and the DOM node a\n // `StackItem` (e.g. StaticToast) later portals into (calling\n // `getRootElement` again with the same, possibly-undefined `container`)\n // would otherwise resolve two different containers here, splitting the\n // React tree (correctly under the root Config, via ConfigSnapshotProvider\n // above) from the actual visible DOM (silently back under `document.body`,\n // outside the Config's themed wrapper — undoing this fix's whole point).\n const resolveContainer = (container?: HTMLElement): HTMLElement =>\n container || getRootConfigValue()?.getContainer() || document.body;\n\n const getRootElement = (container?: HTMLElement): HTMLElement | null => {\n if (!isBrowser) {\n return null;\n }\n\n const targetContainer = resolveContainer(container);\n let rootEl = rootElements.get(targetContainer);\n\n if (!rootEl) {\n rootEl = createRootElement();\n targetContainer.appendChild(rootEl);\n rootElements.set(targetContainer, rootEl);\n }\n\n return rootEl;\n };\n\n const StackRenderer = ({ container }: { container: HTMLElement }) => {\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n const state = getContainerState(container);\n state.update = onStoreChange;\n return () => {\n state.update = null;\n };\n },\n [container],\n );\n\n const getSnapshot = useCallback(\n () => getContainerState(container).stack,\n [container],\n );\n\n const stack = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return (\n <ConfigSnapshotProvider>\n {stack.map(({ id, ...props }) => (\n <StackItem key={id} id={id} {...(props as TProps)} />\n ))}\n </ConfigSnapshotProvider>\n );\n };\n\n const render = (props: TProps): string | undefined => {\n if (!isBrowser) {\n return;\n }\n\n // An explicit `container` prop always wins (it may be chosen for\n // layout reasons unrelated to theming); otherwise mount into the root\n // Config's own themed wrapper element (if one renders — see\n // `needsWrapper` in config.tsx) so CSS custom properties and the\n // `.dark` class cascade to this stack via normal DOM inheritance, not\n // just `document.body` sitting as an unthemed sibling of it.\n const targetContainer = resolveContainer(props.container);\n const rootElement = getRootElement(targetContainer)!;\n\n if (!reactRoots.has(targetContainer)) {\n const root = createRoot(rootElement);\n reactRoots.set(targetContainer, root);\n root.render(<StackRenderer container={targetContainer} />);\n }\n\n const state = getContainerState(targetContainer);\n const id = props.id || uuid();\n state.stack = [...state.stack, { ...props, id }];\n state.update?.();\n\n return id;\n };\n\n const destroy = (id?: string) => {\n if (!id) {\n containerStates.forEach(state => {\n state.stack = [];\n state.update?.();\n });\n reactRoots.forEach((root, container) => {\n root.unmount();\n rootElements.get(container)?.remove();\n rootElements.delete(container);\n });\n reactRoots.clear();\n containerStates.clear();\n return;\n }\n\n containerStates.forEach((state, container) => {\n if (!state.stack.some(item => item.id === id)) {\n return;\n }\n\n state.stack = state.stack.filter(item => item.id !== id);\n state.update?.();\n\n if (!state.stack.length) {\n reactRoots.get(container)?.unmount();\n reactRoots.delete(container);\n containerStates.delete(container);\n rootElements.get(container)?.remove();\n rootElements.delete(container);\n }\n });\n };\n\n return { render, destroy, getRootElement };\n}\n"],"mappings":";;;;;;;AAiBA,MAAa,YACX,OAAO,WAAW,eAAe,OAAO,aAAa;AA2BvD,SAAgB,sBAEd,EACA,mBACA,aAC0D;CAC1D,MAAM,kCAAkB,IAAI,IAAyC;CACrE,MAAM,+BAAe,IAAI,QAAkC;CAC3D,MAAM,6BAAa,IAAI,IAAuB;CAE9C,MAAM,qBACJ,cAC2B;EAC3B,IAAI,QAAQ,gBAAgB,IAAI,SAAS;EAEzC,IAAI,CAAC,OAAO;GACV,QAAQ;IAAE,OAAO,CAAC;IAAG,QAAQ;GAAK;GAClC,gBAAgB,IAAI,WAAW,KAAK;EACtC;EAEA,OAAO;CACT;CAWA,MAAM,oBAAoB,cACxB,aAAa,mBAAmB,CAAC,EAAE,aAAa,KAAK,SAAS;CAEhE,MAAM,kBAAkB,cAAgD;EACtE,IAAI,CAAC,WACH,OAAO;EAGT,MAAM,kBAAkB,iBAAiB,SAAS;EAClD,IAAI,SAAS,aAAa,IAAI,eAAe;EAE7C,IAAI,CAAC,QAAQ;GACX,SAAS,kBAAkB;GAC3B,gBAAgB,YAAY,MAAM;GAClC,aAAa,IAAI,iBAAiB,MAAM;EAC1C;EAEA,OAAO;CACT;CAEA,MAAM,iBAAiB,EAAE,gBAA4C;EACnE,MAAM,YAAY,aACf,kBAA8B;GAC7B,MAAM,QAAQ,kBAAkB,SAAS;GACzC,MAAM,SAAS;GACf,aAAa;IACX,MAAM,SAAS;GACjB;EACF,GACA,CAAC,SAAS,CACZ;EAEA,MAAM,cAAc,kBACZ,kBAAkB,SAAS,CAAC,CAAC,OACnC,CAAC,SAAS,CACZ;EAEA,MAAM,QAAQ,qBAAqB,WAAW,aAAa,WAAW;EAEtE,OACE,oBAAC,wBAAD,EAAA,UACG,MAAM,KAAK,EAAE,IAAI,GAAG,YACnB,oBAAC,WAAD;GAAwB;GAAI,GAAK;EAAmB,GAApC,EAAoC,CACrD,EACqB,CAAA;CAE5B;CAEA,MAAM,UAAU,UAAsC;EACpD,IAAI,CAAC,WACH;EASF,MAAM,kBAAkB,iBAAiB,MAAM,SAAS;EACxD,MAAM,cAAc,eAAe,eAAe;EAElD,IAAI,CAAC,WAAW,IAAI,eAAe,GAAG;GACpC,MAAM,OAAO,WAAW,WAAW;GACnC,WAAW,IAAI,iBAAiB,IAAI;GACpC,KAAK,OAAO,oBAAC,eAAD,EAAe,WAAW,gBAAkB,CAAA,CAAC;EAC3D;EAEA,MAAM,QAAQ,kBAAkB,eAAe;EAC/C,MAAM,KAAK,MAAM,MAAMA,GAAK;EAC5B,MAAM,QAAQ,CAAC,GAAG,MAAM,OAAO;GAAE,GAAG;GAAO;EAAG,CAAC;EAC/C,MAAM,SAAS;EAEf,OAAO;CACT;CAEA,MAAM,WAAW,OAAgB;EAC/B,IAAI,CAAC,IAAI;GACP,gBAAgB,SAAQ,UAAS;IAC/B,MAAM,QAAQ,CAAC;IACf,MAAM,SAAS;GACjB,CAAC;GACD,WAAW,SAAS,MAAM,cAAc;IACtC,KAAK,QAAQ;IACb,aAAa,IAAI,SAAS,CAAC,EAAE,OAAO;IACpC,aAAa,OAAO,SAAS;GAC/B,CAAC;GACD,WAAW,MAAM;GACjB,gBAAgB,MAAM;GACtB;EACF;EAEA,gBAAgB,SAAS,OAAO,cAAc;GAC5C,IAAI,CAAC,MAAM,MAAM,MAAK,SAAQ,KAAK,OAAO,EAAE,GAC1C;GAGF,MAAM,QAAQ,MAAM,MAAM,QAAO,SAAQ,KAAK,OAAO,EAAE;GACvD,MAAM,SAAS;GAEf,IAAI,CAAC,MAAM,MAAM,QAAQ;IACvB,WAAW,IAAI,SAAS,CAAC,EAAE,QAAQ;IACnC,WAAW,OAAO,SAAS;IAC3B,gBAAgB,OAAO,SAAS;IAChC,aAAa,IAAI,SAAS,CAAC,EAAE,OAAO;IACpC,aAAa,OAAO,SAAS;GAC/B;EACF,CAAC;CACH;CAEA,OAAO;EAAE;EAAQ;EAAS;CAAe;AAC3C"}
@@ -4,7 +4,7 @@ declare namespace badge_d_exports {
4
4
  export { Badge, Props, badgeVariants };
5
5
  }
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
7
+ variant?: "outline" | "default" | "destructive" | "secondary" | null | undefined;
8
8
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
9
  type Props = React$1.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & {
10
10
  asChild?: boolean;
@@ -4,7 +4,7 @@ declare namespace button_d_exports {
4
4
  export { Button, Props, buttonVariants };
5
5
  }
6
6
  declare const buttonVariants: (props?: ({
7
- variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
7
+ variant?: "link" | "outline" | "default" | "destructive" | "secondary" | "ghost" | null | undefined;
8
8
  size?: "icon" | "default" | "xs" | "sm" | "lg" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
10
  type Props = React$1.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
package/dist/style.css CHANGED
@@ -61,156 +61,9 @@
61
61
  --animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
62
62
  --default-transition-duration: .15s;
63
63
  --default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
64
- --default-font-family: var(--font-geist-sans);
65
- --default-mono-font-family: var(--font-geist-mono);
66
64
  }
67
65
  }
68
66
  @layer base {
69
- *, :after, :before, ::backdrop, ::file-selector-button {
70
- box-sizing: border-box;
71
- border: 0 solid;
72
- margin: 0;
73
- padding: 0;
74
- }
75
- html, :host {
76
- -webkit-text-size-adjust: 100%;
77
- tab-size: 4;
78
- line-height: 1.5;
79
- font-family: var(--default-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
80
- font-feature-settings: var(--default-font-feature-settings, normal);
81
- font-variation-settings: var(--default-font-variation-settings, normal);
82
- -webkit-tap-highlight-color: transparent;
83
- }
84
- hr {
85
- height: 0;
86
- color: inherit;
87
- border-top-width: 1px;
88
- }
89
- abbr:where([title]) {
90
- text-decoration: underline dotted;
91
- }
92
- h1, h2, h3, h4, h5, h6 {
93
- font-size: inherit;
94
- font-weight: inherit;
95
- }
96
- a {
97
- color: inherit;
98
- -webkit-text-decoration: inherit;
99
- text-decoration: inherit;
100
- }
101
- b, strong {
102
- font-weight: bolder;
103
- }
104
- code, kbd, samp, pre {
105
- font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
106
- font-feature-settings: var(--default-mono-font-feature-settings, normal);
107
- font-variation-settings: var(--default-mono-font-variation-settings, normal);
108
- font-size: 1em;
109
- }
110
- small {
111
- font-size: 80%;
112
- }
113
- sub, sup {
114
- vertical-align: baseline;
115
- font-size: 75%;
116
- line-height: 0;
117
- position: relative;
118
- }
119
- sub {
120
- bottom: -.25em;
121
- }
122
- sup {
123
- top: -.5em;
124
- }
125
- table {
126
- text-indent: 0;
127
- border-color: inherit;
128
- border-collapse: collapse;
129
- }
130
- :-moz-focusring:where(:not(iframe)) {
131
- outline: auto;
132
- }
133
- progress {
134
- vertical-align: baseline;
135
- }
136
- summary {
137
- display: list-item;
138
- }
139
- ol, ul, menu {
140
- list-style: none;
141
- }
142
- img, svg, video, canvas, audio, iframe, embed, object {
143
- vertical-align: middle;
144
- display: block;
145
- }
146
- img, video {
147
- max-width: 100%;
148
- height: auto;
149
- }
150
- button, input, select, optgroup, textarea, ::file-selector-button {
151
- font: inherit;
152
- font-feature-settings: inherit;
153
- font-variation-settings: inherit;
154
- letter-spacing: inherit;
155
- color: inherit;
156
- opacity: 1;
157
- background-color: #0000;
158
- border-radius: 0;
159
- }
160
- :where(select:is([multiple], [size])) optgroup {
161
- font-weight: bolder;
162
- }
163
- :where(select:is([multiple], [size])) optgroup option {
164
- padding-inline-start: 20px;
165
- }
166
- ::file-selector-button {
167
- margin-inline-end: 4px;
168
- }
169
- ::placeholder {
170
- opacity: 1;
171
- }
172
- @supports (not ((-webkit-appearance: -apple-pay-button))) or (contain-intrinsic-size: 1px) {
173
- ::placeholder {
174
- color: currentcolor;
175
- @supports (color: color-mix(in lab, red, red)) {
176
- color: color-mix(in oklab, currentcolor 50%, transparent);
177
- }
178
- }
179
- }
180
- textarea {
181
- resize: vertical;
182
- }
183
- ::-webkit-search-decoration {
184
- -webkit-appearance: none;
185
- }
186
- ::-webkit-date-and-time-value {
187
- min-height: 1lh;
188
- text-align: inherit;
189
- }
190
- ::-webkit-datetime-edit {
191
- display: inline-flex;
192
- }
193
- ::-webkit-datetime-edit-fields-wrapper {
194
- padding: 0;
195
- }
196
- ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
197
- padding-block: 0;
198
- }
199
- ::-webkit-calendar-picker-indicator {
200
- line-height: 1;
201
- }
202
- :-moz-ui-invalid {
203
- box-shadow: none;
204
- }
205
- button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
206
- appearance: button;
207
- }
208
- ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
209
- height: auto;
210
- }
211
- [hidden]:where(:not([hidden="until-found"])) {
212
- display: none !important;
213
- }
214
67
  * {
215
68
  border-color: var(--border);
216
69
  outline-color: var(--ring);
@@ -218,10 +71,6 @@
218
71
  outline-color: color-mix(in oklab, var(--ring) 50%, transparent);
219
72
  }
220
73
  }
221
- body {
222
- background-color: var(--background);
223
- color: var(--foreground);
224
- }
225
74
  }
226
75
  @layer components {
227
76
  [data-slot="button"][data-color] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbpark/ui-kit",
3
- "version": "5.3.0",
3
+ "version": "5.4.0",
4
4
  "description": "Modern React UI component library built with TypeScript, Tailwind CSS, and Radix UI. Featuring atoms, molecules, organisms and layout templates for building beautiful interfaces.",
5
5
  "keywords": [
6
6
  "react",