@jbpark/ui-kit 3.8.0 → 4.0.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.
Files changed (101) hide show
  1. package/dist/components/atoms/float-button/back-top.d.mts.map +1 -1
  2. package/dist/components/atoms/float-button/back-top.mjs +3 -1
  3. package/dist/components/atoms/float-button/back-top.mjs.map +1 -1
  4. package/dist/components/atoms/input/search.d.mts.map +1 -1
  5. package/dist/components/atoms/input/search.mjs +3 -1
  6. package/dist/components/atoms/input/search.mjs.map +1 -1
  7. package/dist/components/atoms/skeleton/skeleton.d.mts.map +1 -1
  8. package/dist/components/atoms/skeleton/skeleton.mjs +5 -1
  9. package/dist/components/atoms/skeleton/skeleton.mjs.map +1 -1
  10. package/dist/components/atoms/spin.d.mts.map +1 -1
  11. package/dist/components/atoms/spin.mjs +7 -2
  12. package/dist/components/atoms/spin.mjs.map +1 -1
  13. package/dist/components/organisms/drawer.d.mts.map +1 -1
  14. package/dist/components/organisms/drawer.mjs +3 -1
  15. package/dist/components/organisms/drawer.mjs.map +1 -1
  16. package/dist/components/organisms/imperative-stack.mjs +106 -0
  17. package/dist/components/organisms/imperative-stack.mjs.map +1 -0
  18. package/dist/components/organisms/index.d.mts +3 -1
  19. package/dist/components/organisms/list/index.d.mts +1 -1
  20. package/dist/components/organisms/list/index.mjs.map +1 -1
  21. package/dist/components/organisms/list/list.d.mts +2 -2
  22. package/dist/components/organisms/list/list.d.mts.map +1 -1
  23. package/dist/components/organisms/list/list.mjs +20 -11
  24. package/dist/components/organisms/list/list.mjs.map +1 -1
  25. package/dist/components/organisms/modal.d.mts +2 -2
  26. package/dist/components/organisms/modal.d.mts.map +1 -1
  27. package/dist/components/organisms/modal.mjs +21 -101
  28. package/dist/components/organisms/modal.mjs.map +1 -1
  29. package/dist/components/organisms/swiper/index.d.mts +1 -1
  30. package/dist/components/organisms/swiper/index.mjs.map +1 -1
  31. package/dist/components/organisms/swiper/swiper.d.mts +2 -1
  32. package/dist/components/organisms/swiper/swiper.d.mts.map +1 -1
  33. package/dist/components/organisms/swiper/swiper.mjs +5 -3
  34. package/dist/components/organisms/swiper/swiper.mjs.map +1 -1
  35. package/dist/components/organisms/toast.d.mts +1 -1
  36. package/dist/components/organisms/toast.d.mts.map +1 -1
  37. package/dist/components/organisms/toast.mjs +35 -111
  38. package/dist/components/organisms/toast.mjs.map +1 -1
  39. package/dist/components/templates/container.d.mts +19 -0
  40. package/dist/components/templates/container.d.mts.map +1 -0
  41. package/dist/components/templates/container.mjs +32 -0
  42. package/dist/components/templates/container.mjs.map +1 -0
  43. package/dist/components/templates/empty.d.mts +20 -0
  44. package/dist/components/templates/empty.d.mts.map +1 -0
  45. package/dist/components/templates/empty.mjs +34 -0
  46. package/dist/components/templates/empty.mjs.map +1 -0
  47. package/dist/components/templates/grid/col.d.mts +35 -0
  48. package/dist/components/templates/grid/col.d.mts.map +1 -0
  49. package/dist/components/templates/grid/col.mjs +55 -0
  50. package/dist/components/templates/grid/col.mjs.map +1 -0
  51. package/dist/components/templates/grid/index.d.mts +2 -0
  52. package/dist/components/templates/grid/row-context.mjs +13 -0
  53. package/dist/components/templates/grid/row-context.mjs.map +1 -0
  54. package/dist/components/templates/grid/row.d.mts +36 -0
  55. package/dist/components/templates/grid/row.d.mts.map +1 -0
  56. package/dist/components/templates/grid/row.mjs +54 -0
  57. package/dist/components/templates/grid/row.mjs.map +1 -0
  58. package/dist/components/templates/index.d.mts +13 -1
  59. package/dist/components/templates/layout/content.d.mts +4 -1
  60. package/dist/components/templates/layout/content.d.mts.map +1 -1
  61. package/dist/components/templates/layout/content.mjs +3 -2
  62. package/dist/components/templates/layout/content.mjs.map +1 -1
  63. package/dist/components/templates/layout/footer.d.mts +1 -1
  64. package/dist/components/templates/layout/footer.d.mts.map +1 -1
  65. package/dist/components/templates/layout/footer.mjs.map +1 -1
  66. package/dist/components/templates/layout/header.d.mts +4 -1
  67. package/dist/components/templates/layout/header.d.mts.map +1 -1
  68. package/dist/components/templates/layout/header.mjs +2 -2
  69. package/dist/components/templates/layout/header.mjs.map +1 -1
  70. package/dist/components/templates/layout/layout.d.mts +1 -1
  71. package/dist/components/templates/layout/layout.d.mts.map +1 -1
  72. package/dist/components/templates/layout/layout.mjs.map +1 -1
  73. package/dist/components/templates/layout/sider.d.mts +9 -2
  74. package/dist/components/templates/layout/sider.d.mts.map +1 -1
  75. package/dist/components/templates/layout/sider.mjs +40 -13
  76. package/dist/components/templates/layout/sider.mjs.map +1 -1
  77. package/dist/components/templates/page-header.d.mts +30 -0
  78. package/dist/components/templates/page-header.d.mts.map +1 -0
  79. package/dist/components/templates/page-header.mjs +45 -0
  80. package/dist/components/templates/page-header.mjs.map +1 -0
  81. package/dist/components/templates/result.d.mts +24 -0
  82. package/dist/components/templates/result.d.mts.map +1 -0
  83. package/dist/components/templates/result.mjs +46 -0
  84. package/dist/components/templates/result.mjs.map +1 -0
  85. package/dist/index.d.mts +28 -15
  86. package/dist/index.mjs +9 -3
  87. package/dist/providers/Config/context.d.mts +3 -2
  88. package/dist/providers/Config/context.d.mts.map +1 -1
  89. package/dist/providers/Config/context.mjs +13 -2
  90. package/dist/providers/Config/context.mjs.map +1 -1
  91. package/dist/providers/Config/index.d.mts +4 -2
  92. package/dist/providers/Config/index.d.mts.map +1 -1
  93. package/dist/providers/Config/index.mjs +14 -4
  94. package/dist/providers/Config/index.mjs.map +1 -1
  95. package/dist/providers/Config/types.d.mts +10 -1
  96. package/dist/providers/Config/types.d.mts.map +1 -1
  97. package/dist/providers.d.mts +4 -0
  98. package/dist/providers.mjs +4 -0
  99. package/dist/style.css +114 -0
  100. package/package.json +3 -3
  101. package/dist/providers/index.d.mts +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"back-top.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"mappings":";;;;;UAYiB,KAAA,SAAc,OAAA;EAC7B,gBAAA;EACA,OAAA,IAAW,CAAA,EAAG,UAAA,CAAW,WAAA;AAAA;AAAA,cAGrB,OAAA;EAAW,GAAA;EAAA,gBAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAMd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"back-top.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"mappings":";;;;;UAaiB,KAAA,SAAc,OAAA;EAC7B,gBAAA;EACA,OAAA,IAAW,CAAA,EAAG,UAAA,CAAW,WAAA;AAAA;AAAA,cAGrB,OAAA;EAAW,GAAA;EAAA,gBAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAMd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../../utils.mjs";
4
+ import { DEFAULT_LOCALE, useConfig } from "../../../providers/Config/context.mjs";
4
5
  import FloatButton from "./float-button.mjs";
5
6
  import { ArrowUp } from "lucide-react";
6
7
  import { useRef } from "react";
@@ -9,11 +10,12 @@ import { useMergedRef, useWindowScroll } from "@jbpark/use-hooks";
9
10
 
10
11
  //#region src/components/atoms/float-button/back-top.tsx
11
12
  const BackTop = ({ ref, visibilityHeight = 450, className, onClick, ...props }) => {
13
+ const { locale } = useConfig();
12
14
  const buttonRef = useRef(null);
13
15
  const { y } = useWindowScroll(buttonRef);
14
16
  return /* @__PURE__ */ jsx(FloatButton, {
15
17
  ref: useMergedRef(buttonRef, ref),
16
- "aria-label": "맨 위로",
18
+ "aria-label": locale.backToTop ?? DEFAULT_LOCALE.backToTop,
17
19
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
18
20
  className: cn(className, (!y || visibilityHeight > y) && "hidden"),
19
21
  onClick: (e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { type MouseEvent, useRef } from 'react';\n\nimport { useMergedRef, useWindowScroll } from '@jbpark/use-hooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n ref,\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n // Track/scroll whichever window actually renders this button — not\n // necessarily the host `window`, since this can be portaled into an\n // iframe (e.g. live-editor's Renderer).\n const { y } = useWindowScroll(buttonRef);\n\n const mergedRef = useMergedRef(buttonRef, ref);\n\n return (\n <FloatButton\n ref={mergedRef}\n aria-label=\"맨 위로\"\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n const view = buttonRef.current?.ownerDocument.defaultView ?? window;\n view.scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;;AAiBA,MAAM,WAAW,EACf,KACA,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,YAAY,OAA0B,KAAK;CAKjD,MAAM,EAAE,MAAM,gBAAgB,UAAU;AAIxC,QACE,oBAAC;EACC,KAJc,aAAa,WAAW,IAAI;EAK1C,cAAW;EACX,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AAEZ,IADa,UAAU,SAAS,cAAc,eAAe,QACxD,SAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACtD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
1
+ {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { type MouseEvent, useRef } from 'react';\n\nimport { useMergedRef, useWindowScroll } from '@jbpark/use-hooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n ref,\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n // Track/scroll whichever window actually renders this button — not\n // necessarily the host `window`, since this can be portaled into an\n // iframe (e.g. live-editor's Renderer).\n const { y } = useWindowScroll(buttonRef);\n\n const mergedRef = useMergedRef(buttonRef, ref);\n\n return (\n <FloatButton\n ref={mergedRef}\n aria-label={locale.backToTop ?? DEFAULT_LOCALE.backToTop}\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n const view = buttonRef.current?.ownerDocument.defaultView ?? window;\n view.scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;;;AAkBA,MAAM,WAAW,EACf,KACA,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,YAAY,OAA0B,KAAK;CAKjD,MAAM,EAAE,MAAM,gBAAgB,UAAU;AAIxC,QACE,oBAAC;EACC,KAJc,aAAa,WAAW,IAAI;EAK1C,cAAY,OAAO,aAAa,eAAe;EAC/C,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AAEZ,IADa,UAAU,SAAS,cAAc,eAAe,QACxD,SAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACtD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.mts","names":[],"sources":["../../../../src/components/atoms/input/search.tsx"],"mappings":";;;UAciB,KAAA,SAAc,KAAA,CAAM,qBAAA;EACnC,UAAA;EACA,QAAA,IACE,CAAA,EAAG,KAAA,CAAM,WAAA,CAAY,gBAAA;IAAsB,MAAA;MAAU,KAAA;IAAA;EAAA;EAEvD,QAAA,IAAY,KAAA;AAAA;AAAA,cAGR,MAAA;EAAA;;;;;;;;;;;KAWH,KAAA,GAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"search.d.mts","names":[],"sources":["../../../../src/components/atoms/input/search.tsx"],"mappings":";;;UAeiB,KAAA,SAAc,KAAA,CAAM,qBAAA;EACnC,UAAA;EACA,QAAA,IACE,CAAA,EAAG,KAAA,CAAM,WAAA,CAAY,gBAAA;IAAsB,MAAA;MAAU,KAAA;IAAA;EAAA;EAEvD,QAAA,IAAY,KAAA;AAAA;AAAA,cAGR,MAAA;EAAA;;;;;;;;;;;KAWH,KAAA,GAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,6 +3,7 @@
3
3
  import { cn } from "../../../utils.mjs";
4
4
  import { input_exports } from "../../../core/input.mjs";
5
5
  import Button from "../../../Button.mjs";
6
+ import { DEFAULT_LOCALE, useConfig } from "../../../providers/Config/context.mjs";
6
7
  import { CircleX, Search } from "lucide-react";
7
8
  import { useRef, useState } from "react";
8
9
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -11,6 +12,7 @@ import { useMergedRef } from "@jbpark/use-hooks";
11
12
  //#region src/components/atoms/input/search.tsx
12
13
  const { Input: Core } = input_exports;
13
14
  const Search$1 = ({ ref, className, defaultValue, value, disabled, allowClear = true, onChange, onKeyDown: _onKeyDown, onSearch: _onSearch, ...props }) => {
15
+ const { locale } = useConfig();
14
16
  const inputRef = useRef(null);
15
17
  const mergedRef = useMergedRef(inputRef, ref);
16
18
  const [uncontrolledHasValue, setUncontrolledHasValue] = useState(!!defaultValue);
@@ -51,7 +53,7 @@ const Search$1 = ({ ref, className, defaultValue, value, disabled, allowClear =
51
53
  }
52
54
  }), /* @__PURE__ */ jsx("button", {
53
55
  type: "button",
54
- "aria-label": "지우기",
56
+ "aria-label": locale.clear ?? DEFAULT_LOCALE.clear,
55
57
  disabled,
56
58
  className: cn("absolute right-2", "shrink-0 cursor-pointer", "disabled:cursor-not-allowed disabled:opacity-50", (!allowClear || !hasValue) && "hidden"),
57
59
  onClick: onClear,
@@ -1 +1 @@
1
- {"version":3,"file":"search.mjs","names":["input","Search","SearchOutlined"],"sources":["../../../../src/components/atoms/input/search.tsx"],"sourcesContent":["'use client';\n\nimport { useRef, useState } from 'react';\n\nimport { useMergedRef } from '@jbpark/use-hooks';\nimport { CircleX, Search as SearchOutlined } from 'lucide-react';\n\nimport { input } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../button';\n\nconst { Input: Core } = input;\n\nexport interface Props extends React.ComponentPropsWithRef<'input'> {\n allowClear?: boolean;\n onChange?: (\n e: React.ChangeEvent<HTMLInputElement> | { target: { value: string } },\n ) => void;\n onSearch?: (value: string) => void;\n}\n\nconst Search = ({\n ref,\n className,\n defaultValue,\n value,\n disabled,\n allowClear = true,\n onChange,\n onKeyDown: _onKeyDown,\n onSearch: _onSearch,\n ...props\n}: Props) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const mergedRef = useMergedRef(inputRef, ref);\n\n const [uncontrolledHasValue, setUncontrolledHasValue] =\n useState(!!defaultValue);\n const hasValue = value !== undefined ? !!value : uncontrolledHasValue;\n\n const onClear = () => {\n if (!inputRef.current) {\n return;\n }\n\n if (value === undefined) {\n inputRef.current.value = '';\n setUncontrolledHasValue(false);\n }\n\n onChange?.({ target: { value: '' } });\n };\n\n const onSearch = () => {\n if (disabled) {\n return;\n }\n if (inputRef.current) {\n _onSearch?.(inputRef.current.value);\n }\n };\n\n return (\n <div\n className={cn(\n 'flex items-center',\n 'rounded-md',\n className,\n //\n )}\n >\n <div\n className={cn(\n 'relative grow',\n 'inline-flex items-center',\n //\n )}\n >\n <Core\n {...props}\n ref={mergedRef}\n inputMode=\"search\"\n type=\"search\"\n enterKeyHint=\"search\"\n disabled={disabled}\n className={cn(\n 'rounded-r-none',\n '[&::-webkit-search-cancel-button]:hidden',\n '[&::-webkit-search-decoration]:hidden',\n //\n )}\n value={value}\n defaultValue={defaultValue}\n onChange={e => {\n if (value === undefined) {\n setUncontrolledHasValue(!!e.target.value);\n }\n onChange?.(e);\n }}\n onKeyDown={e => {\n _onKeyDown?.(e);\n if (e.key === 'Enter') {\n onSearch();\n }\n }}\n />\n <button\n type=\"button\"\n aria-label=\"지우기\"\n disabled={disabled}\n className={cn(\n 'absolute right-2',\n 'shrink-0 cursor-pointer',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n (!allowClear || !hasValue) && 'hidden',\n )}\n onClick={onClear}\n >\n <CircleX className=\"size-4\" />\n </button>\n </div>\n <Button\n icon={<SearchOutlined />}\n disabled={disabled}\n className={cn(\n 'rounded-l-none',\n 'size-9',\n //\n )}\n onClick={onSearch}\n />\n </div>\n );\n};\n\nSearch.displayName = 'Search';\n\nexport default Search;\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,EAAE,OAAO,SAASA;AAUxB,MAAMC,YAAU,EACd,KACA,WACA,cACA,OACA,UACA,aAAa,MACb,UACA,WAAW,YACX,UAAU,WACV,GAAG,YACQ;CACX,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,YAAY,aAAa,UAAU,IAAI;CAE7C,MAAM,CAAC,sBAAsB,2BAC3B,SAAS,CAAC,CAAC,aAAa;CAC1B,MAAM,WAAW,UAAU,SAAY,CAAC,CAAC,QAAQ;CAEjD,MAAM,gBAAgB;AACpB,MAAI,CAAC,SAAS,QACZ;AAGF,MAAI,UAAU,QAAW;AACvB,YAAS,QAAQ,QAAQ;AACzB,2BAAwB,MAAM;;AAGhC,aAAW,EAAE,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;;CAGvC,MAAM,iBAAiB;AACrB,MAAI,SACF;AAEF,MAAI,SAAS,QACX,aAAY,SAAS,QAAQ,MAAM;;AAIvC,QACE,qBAAC;EACC,WAAW,GACT,qBACA,cACA,UAED;aAED,qBAAC;GACC,WAAW,GACT,iBACA,2BAED;cAED,oBAAC;IACC,GAAI;IACJ,KAAK;IACL,WAAU;IACV,MAAK;IACL,cAAa;IACH;IACV,WAAW,GACT,kBACA,4CACA,wCAED;IACM;IACO;IACd,WAAU,MAAK;AACb,SAAI,UAAU,OACZ,yBAAwB,CAAC,CAAC,EAAE,OAAO,MAAM;AAE3C,gBAAW,EAAE;;IAEf,YAAW,MAAK;AACd,kBAAa,EAAE;AACf,SAAI,EAAE,QAAQ,QACZ,WAAU;;KAGd,EACF,oBAAC;IACC,MAAK;IACL,cAAW;IACD;IACV,WAAW,GACT,oBACA,2BACA,oDACC,CAAC,cAAc,CAAC,aAAa,SAC/B;IACD,SAAS;cAET,oBAAC,WAAQ,WAAU,WAAW;KACvB;IACL,EACN,oBAAC;GACC,MAAM,oBAACC,WAAiB;GACd;GACV,WAAW,GACT,kBACA,SAED;GACD,SAAS;IACT;GACE;;AAIV,SAAO,cAAc"}
1
+ {"version":3,"file":"search.mjs","names":["input","Search","SearchOutlined"],"sources":["../../../../src/components/atoms/input/search.tsx"],"sourcesContent":["'use client';\n\nimport { useRef, useState } from 'react';\n\nimport { useMergedRef } from '@jbpark/use-hooks';\nimport { CircleX, Search as SearchOutlined } from 'lucide-react';\n\nimport { input } from '@repo/ui/core';\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../button';\n\nconst { Input: Core } = input;\n\nexport interface Props extends React.ComponentPropsWithRef<'input'> {\n allowClear?: boolean;\n onChange?: (\n e: React.ChangeEvent<HTMLInputElement> | { target: { value: string } },\n ) => void;\n onSearch?: (value: string) => void;\n}\n\nconst Search = ({\n ref,\n className,\n defaultValue,\n value,\n disabled,\n allowClear = true,\n onChange,\n onKeyDown: _onKeyDown,\n onSearch: _onSearch,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n const inputRef = useRef<HTMLInputElement>(null);\n\n const mergedRef = useMergedRef(inputRef, ref);\n\n const [uncontrolledHasValue, setUncontrolledHasValue] =\n useState(!!defaultValue);\n const hasValue = value !== undefined ? !!value : uncontrolledHasValue;\n\n const onClear = () => {\n if (!inputRef.current) {\n return;\n }\n\n if (value === undefined) {\n inputRef.current.value = '';\n setUncontrolledHasValue(false);\n }\n\n onChange?.({ target: { value: '' } });\n };\n\n const onSearch = () => {\n if (disabled) {\n return;\n }\n if (inputRef.current) {\n _onSearch?.(inputRef.current.value);\n }\n };\n\n return (\n <div\n className={cn(\n 'flex items-center',\n 'rounded-md',\n className,\n //\n )}\n >\n <div\n className={cn(\n 'relative grow',\n 'inline-flex items-center',\n //\n )}\n >\n <Core\n {...props}\n ref={mergedRef}\n inputMode=\"search\"\n type=\"search\"\n enterKeyHint=\"search\"\n disabled={disabled}\n className={cn(\n 'rounded-r-none',\n '[&::-webkit-search-cancel-button]:hidden',\n '[&::-webkit-search-decoration]:hidden',\n //\n )}\n value={value}\n defaultValue={defaultValue}\n onChange={e => {\n if (value === undefined) {\n setUncontrolledHasValue(!!e.target.value);\n }\n onChange?.(e);\n }}\n onKeyDown={e => {\n _onKeyDown?.(e);\n if (e.key === 'Enter') {\n onSearch();\n }\n }}\n />\n <button\n type=\"button\"\n aria-label={locale.clear ?? DEFAULT_LOCALE.clear}\n disabled={disabled}\n className={cn(\n 'absolute right-2',\n 'shrink-0 cursor-pointer',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n (!allowClear || !hasValue) && 'hidden',\n )}\n onClick={onClear}\n >\n <CircleX className=\"size-4\" />\n </button>\n </div>\n <Button\n icon={<SearchOutlined />}\n disabled={disabled}\n className={cn(\n 'rounded-l-none',\n 'size-9',\n //\n )}\n onClick={onSearch}\n />\n </div>\n );\n};\n\nSearch.displayName = 'Search';\n\nexport default Search;\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,EAAE,OAAO,SAASA;AAUxB,MAAMC,YAAU,EACd,KACA,WACA,cACA,OACA,UACA,aAAa,MACb,UACA,WAAW,YACX,UAAU,WACV,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,YAAY,aAAa,UAAU,IAAI;CAE7C,MAAM,CAAC,sBAAsB,2BAC3B,SAAS,CAAC,CAAC,aAAa;CAC1B,MAAM,WAAW,UAAU,SAAY,CAAC,CAAC,QAAQ;CAEjD,MAAM,gBAAgB;AACpB,MAAI,CAAC,SAAS,QACZ;AAGF,MAAI,UAAU,QAAW;AACvB,YAAS,QAAQ,QAAQ;AACzB,2BAAwB,MAAM;;AAGhC,aAAW,EAAE,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC;;CAGvC,MAAM,iBAAiB;AACrB,MAAI,SACF;AAEF,MAAI,SAAS,QACX,aAAY,SAAS,QAAQ,MAAM;;AAIvC,QACE,qBAAC;EACC,WAAW,GACT,qBACA,cACA,UAED;aAED,qBAAC;GACC,WAAW,GACT,iBACA,2BAED;cAED,oBAAC;IACC,GAAI;IACJ,KAAK;IACL,WAAU;IACV,MAAK;IACL,cAAa;IACH;IACV,WAAW,GACT,kBACA,4CACA,wCAED;IACM;IACO;IACd,WAAU,MAAK;AACb,SAAI,UAAU,OACZ,yBAAwB,CAAC,CAAC,EAAE,OAAO,MAAM;AAE3C,gBAAW,EAAE;;IAEf,YAAW,MAAK;AACd,kBAAa,EAAE;AACf,SAAI,EAAE,QAAQ,QACZ,WAAU;;KAGd,EACF,oBAAC;IACC,MAAK;IACL,cAAY,OAAO,SAAS,eAAe;IACjC;IACV,WAAW,GACT,oBACA,2BACA,oDACC,CAAC,cAAc,CAAC,aAAa,SAC/B;IACD,SAAS;cAET,oBAAC,WAAQ,WAAU,WAAW;KACvB;IACL,EACN,oBAAC;GACC,MAAM,oBAACC,WAAiB;GACd;GACV,WAAW,GACT,kBACA,SAED;GACD,SAAS;IACT;GACE;;AAIV,SAAO,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"mappings":";;;;UASiB,KAAA,SAAc,KAAA,CAAM,wBAAA;EACnC,MAAA;EACA,OAAA;EACA,MAAA;EACA,IAAA;EACA,KAAA;EACA,GAAA;EACA,SAAA;EACA,KAAA;EACA,MAAA;EACA,UAAA;IACE,OAAA;IACA,MAAA;IACA,IAAA;EAAA;AAAA;AAAA,cAUE,QAAA;EAAY,MAAA;EAAA,OAAA;EAAA,MAAA;EAAA,IAAA;EAAA,SAAA;EAAA,KAAA;EAAA,GAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAef,KAAA,0CAAK,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA,wBAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"skeleton.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"mappings":";;;;UAYiB,KAAA,SAAc,KAAA,CAAM,wBAAA;EACnC,MAAA;EACA,OAAA;EACA,MAAA;EACA,IAAA;EACA,KAAA;EACA,GAAA;EACA,SAAA;EACA,KAAA;EACA,MAAA;EACA,UAAA;IACE,OAAA;IACA,MAAA;IACA,IAAA;EAAA;AAAA;AAAA,cAUE,QAAA;EAAY,MAAA;EAAA,OAAA;EAAA,MAAA;EAAA,IAAA;EAAA,SAAA;EAAA,KAAA;EAAA,GAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAef,KAAA,0CAAK,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA,wBAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,5 +1,8 @@
1
+ 'use client';
2
+
1
3
  import { cn } from "../../../utils.mjs";
2
4
  import { skeleton_exports } from "../../../core/skeleton.mjs";
5
+ import { DEFAULT_LOCALE, useConfig } from "../../../providers/Config/context.mjs";
3
6
  import { jsx, jsxs } from "react/jsx-runtime";
4
7
 
5
8
  //#region src/components/atoms/skeleton/skeleton.tsx
@@ -13,10 +16,11 @@ const SIZES = {
13
16
  large: "w-72 h-8"
14
17
  };
15
18
  const Skeleton = ({ active = true, loading = true, avatar, size = "default", direction = "vertical", count = 1, gap = 6, className, classNames = {}, style, width, height, children, ...props }) => {
19
+ const { locale } = useConfig();
16
20
  if (!loading) return children ?? null;
17
21
  return /* @__PURE__ */ jsxs("div", {
18
22
  role: "status",
19
- "aria-label": "로딩 중",
23
+ "aria-label": locale.loading ?? DEFAULT_LOCALE.loading,
20
24
  className: cn("flex items-center gap-3", className),
21
25
  ...props,
22
26
  children: [avatar && /* @__PURE__ */ jsx(Core, { className: cn("h-12 w-12", "rounded-xl", !active && "animate-none", classNames.avatar) }), /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.mjs","names":["skeleton"],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"sourcesContent":["import { skeleton } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst { Skeleton: Core } = skeleton;\n\nconst getValueAtIndex = <T,>(value: T | T[], index: number) => {\n return Array.isArray(value) ? (value[index] ?? value[0]) : value;\n};\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n active?: boolean;\n loading?: boolean;\n avatar?: boolean;\n size?: 'default' | 'small' | 'large';\n count?: number;\n gap?: number;\n direction?: 'horizontal' | 'vertical';\n width?: string | number | (string | number)[];\n height?: string | number | (string | number)[];\n classNames?: {\n wrapper?: string;\n avatar?: string;\n item?: string;\n };\n}\n\nconst SIZES = {\n small: 'w-48 h-4',\n default: 'w-60 h-6',\n large: 'w-72 h-8',\n};\n\nconst Skeleton = ({\n active = true,\n loading = true,\n avatar,\n size = 'default',\n direction = 'vertical',\n count = 1,\n gap = 6,\n className,\n classNames = {},\n style,\n width,\n height,\n children,\n ...props\n}: Props) => {\n // Not wrapping `children` here (unlike Spin's overlay mode) — Skeleton\n // is meant to swap in arbitrary real content once loading finishes,\n // which can include elements with strict parent requirements (e.g. a\n // `<tr>`), so adding a wrapper div could produce invalid markup.\n // `className`/`style`/rest props only ever describe the skeleton's own\n // placeholder markup, so there's nothing for them to apply to here.\n if (!loading) {\n return children ?? null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label=\"로딩 중\"\n className={cn('flex items-center gap-3', className)}\n {...props}\n >\n {avatar && (\n <Core\n className={cn(\n 'h-12 w-12',\n 'rounded-xl',\n !active && 'animate-none',\n classNames.avatar,\n )}\n />\n )}\n <div\n className={cn(\n 'flex grow',\n direction === 'vertical' && 'flex-col',\n classNames.wrapper,\n )}\n style={{\n gap,\n }}\n >\n {Array.from({ length: count }).map((_, index) => {\n const itemWidth = getValueAtIndex(width, index);\n const itemHeight = getValueAtIndex(height, index);\n\n return (\n <Core\n key={index}\n className={cn(\n 'rounded-md',\n !active && 'animate-none',\n SIZES[size],\n classNames.item,\n //\n )}\n style={{\n ...style,\n width: itemWidth,\n height: itemHeight,\n }}\n />\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default Skeleton;\n"],"mappings":";;;;;AAGA,MAAM,EAAE,UAAU,SAASA;AAE3B,MAAM,mBAAuB,OAAgB,UAAkB;AAC7D,QAAO,MAAM,QAAQ,MAAM,GAAI,MAAM,UAAU,MAAM,KAAM;;AAoB7D,MAAM,QAAQ;CACZ,OAAO;CACP,SAAS;CACT,OAAO;CACR;AAED,MAAM,YAAY,EAChB,SAAS,MACT,UAAU,MACV,QACA,OAAO,WACP,YAAY,YACZ,QAAQ,GACR,MAAM,GACN,WACA,aAAa,EAAE,EACf,OACA,OACA,QACA,UACA,GAAG,YACQ;AAOX,KAAI,CAAC,QACH,QAAO,YAAY;AAGrB,QACE,qBAAC;EACC,MAAK;EACL,cAAW;EACX,WAAW,GAAG,2BAA2B,UAAU;EACnD,GAAI;aAEH,UACC,oBAAC,QACC,WAAW,GACT,aACA,cACA,CAAC,UAAU,gBACX,WAAW,OACZ,GACD,EAEJ,oBAAC;GACC,WAAW,GACT,aACA,cAAc,cAAc,YAC5B,WAAW,QACZ;GACD,OAAO,EACL,KACD;aAEA,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,KAAK,GAAG,UAAU;IAC/C,MAAM,YAAY,gBAAgB,OAAO,MAAM;IAC/C,MAAM,aAAa,gBAAgB,QAAQ,MAAM;AAEjD,WACE,oBAAC;KAEC,WAAW,GACT,cACA,CAAC,UAAU,gBACX,MAAM,OACN,WAAW,KAEZ;KACD,OAAO;MACL,GAAG;MACH,OAAO;MACP,QAAQ;MACT;OAZI,MAaL;KAEJ;IACE;GACF"}
1
+ {"version":3,"file":"skeleton.mjs","names":["skeleton"],"sources":["../../../../src/components/atoms/skeleton/skeleton.tsx"],"sourcesContent":["'use client';\n\nimport { skeleton } from '@repo/ui/core';\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nconst { Skeleton: Core } = skeleton;\n\nconst getValueAtIndex = <T,>(value: T | T[], index: number) => {\n return Array.isArray(value) ? (value[index] ?? value[0]) : value;\n};\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n active?: boolean;\n loading?: boolean;\n avatar?: boolean;\n size?: 'default' | 'small' | 'large';\n count?: number;\n gap?: number;\n direction?: 'horizontal' | 'vertical';\n width?: string | number | (string | number)[];\n height?: string | number | (string | number)[];\n classNames?: {\n wrapper?: string;\n avatar?: string;\n item?: string;\n };\n}\n\nconst SIZES = {\n small: 'w-48 h-4',\n default: 'w-60 h-6',\n large: 'w-72 h-8',\n};\n\nconst Skeleton = ({\n active = true,\n loading = true,\n avatar,\n size = 'default',\n direction = 'vertical',\n count = 1,\n gap = 6,\n className,\n classNames = {},\n style,\n width,\n height,\n children,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n // Not wrapping `children` here (unlike Spin's overlay mode) — Skeleton\n // is meant to swap in arbitrary real content once loading finishes,\n // which can include elements with strict parent requirements (e.g. a\n // `<tr>`), so adding a wrapper div could produce invalid markup.\n // `className`/`style`/rest props only ever describe the skeleton's own\n // placeholder markup, so there's nothing for them to apply to here.\n if (!loading) {\n return children ?? null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label={locale.loading ?? DEFAULT_LOCALE.loading}\n className={cn('flex items-center gap-3', className)}\n {...props}\n >\n {avatar && (\n <Core\n className={cn(\n 'h-12 w-12',\n 'rounded-xl',\n !active && 'animate-none',\n classNames.avatar,\n )}\n />\n )}\n <div\n className={cn(\n 'flex grow',\n direction === 'vertical' && 'flex-col',\n classNames.wrapper,\n )}\n style={{\n gap,\n }}\n >\n {Array.from({ length: count }).map((_, index) => {\n const itemWidth = getValueAtIndex(width, index);\n const itemHeight = getValueAtIndex(height, index);\n\n return (\n <Core\n key={index}\n className={cn(\n 'rounded-md',\n !active && 'animate-none',\n SIZES[size],\n classNames.item,\n //\n )}\n style={{\n ...style,\n width: itemWidth,\n height: itemHeight,\n }}\n />\n );\n })}\n </div>\n </div>\n );\n};\n\nexport default Skeleton;\n"],"mappings":";;;;;;;;AAMA,MAAM,EAAE,UAAU,SAASA;AAE3B,MAAM,mBAAuB,OAAgB,UAAkB;AAC7D,QAAO,MAAM,QAAQ,MAAM,GAAI,MAAM,UAAU,MAAM,KAAM;;AAoB7D,MAAM,QAAQ;CACZ,OAAO;CACP,SAAS;CACT,OAAO;CACR;AAED,MAAM,YAAY,EAChB,SAAS,MACT,UAAU,MACV,QACA,OAAO,WACP,YAAY,YACZ,QAAQ,GACR,MAAM,GACN,WACA,aAAa,EAAE,EACf,OACA,OACA,QACA,UACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,WAAW;AAQ9B,KAAI,CAAC,QACH,QAAO,YAAY;AAGrB,QACE,qBAAC;EACC,MAAK;EACL,cAAY,OAAO,WAAW,eAAe;EAC7C,WAAW,GAAG,2BAA2B,UAAU;EACnD,GAAI;aAEH,UACC,oBAAC,QACC,WAAW,GACT,aACA,cACA,CAAC,UAAU,gBACX,WAAW,OACZ,GACD,EAEJ,oBAAC;GACC,WAAW,GACT,aACA,cAAc,cAAc,YAC5B,WAAW,QACZ;GACD,OAAO,EACL,KACD;aAEA,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,KAAK,GAAG,UAAU;IAC/C,MAAM,YAAY,gBAAgB,OAAO,MAAM;IAC/C,MAAM,aAAa,gBAAgB,QAAQ,MAAM;AAEjD,WACE,oBAAC;KAEC,WAAW,GACT,cACA,CAAC,UAAU,gBACX,MAAM,OACN,WAAW,KAEZ;KACD,OAAO;MACL,GAAG;MACH,OAAO;MACP,QAAQ;MACT;OAZI,MAaL;KAEJ;IACE;GACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"spin.d.mts","names":[],"sources":["../../../src/components/atoms/spin.tsx"],"mappings":";;;;UAIiB,KAAA,SAAc,KAAA,CAAM,wBAAA;EACnC,QAAA;AAAA;AAAA,cAGI,IAAA;EAAQ,QAAA;EAAA,SAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAA6C,KAAA,uCAAK,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA,wBAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"spin.d.mts","names":[],"sources":["../../../src/components/atoms/spin.tsx"],"mappings":";;;;UAOiB,KAAA,SAAc,KAAA,CAAM,wBAAA;EACnC,QAAA;AAAA;AAAA,cAGI,IAAA;EAAQ,QAAA;EAAA,SAAA;EAAA,QAAA;EAAA,GAAA;AAAA,GAA6C,KAAA,uCAAK,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA,wBAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,14 +1,19 @@
1
+ 'use client';
2
+
1
3
  import { cn } from "../../utils.mjs";
4
+ import { DEFAULT_LOCALE, useConfig } from "../../providers/Config/context.mjs";
2
5
  import { Loader2 } from "lucide-react";
3
6
  import { jsx, jsxs } from "react/jsx-runtime";
4
7
 
5
8
  //#region src/components/atoms/spin.tsx
6
9
  const Spin = ({ spinning, className, children, ...props }) => {
10
+ const { locale } = useConfig();
11
+ const loadingLabel = locale.loading ?? DEFAULT_LOCALE.loading;
7
12
  if (!children) {
8
13
  if (!spinning) return null;
9
14
  return /* @__PURE__ */ jsx("div", {
10
15
  role: "status",
11
- "aria-label": "로딩 중",
16
+ "aria-label": loadingLabel,
12
17
  className: cn("flex h-full items-center justify-center", className),
13
18
  ...props,
14
19
  children: /* @__PURE__ */ jsx(Loader2, { className: "animate-spin" })
@@ -23,7 +28,7 @@ const Spin = ({ spinning, className, children, ...props }) => {
23
28
  children
24
29
  }), /* @__PURE__ */ jsx("div", {
25
30
  role: "status",
26
- "aria-label": "로딩 중",
31
+ "aria-label": loadingLabel,
27
32
  className: "absolute inset-0 flex items-center justify-center",
28
33
  children: /* @__PURE__ */ jsx(Loader2, { className: "animate-spin" })
29
34
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"spin.mjs","names":[],"sources":["../../../src/components/atoms/spin.tsx"],"sourcesContent":["import { Loader2 } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n spinning?: boolean;\n}\n\nconst Spin = ({ spinning, className, children, ...props }: Props) => {\n // With no children there's nothing to render at all while idle — unlike\n // the branch below, there's no wrapper for `className`/`props` to land\n // on regardless, so returning null here isn't the same bug.\n if (!children) {\n if (!spinning) {\n return null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label=\"로딩 중\"\n className={cn('flex h-full items-center justify-center', className)}\n {...props}\n >\n <Loader2 className=\"animate-spin\" />\n </div>\n );\n }\n\n // Idle: return children as-is rather than inserting a wrapper div, same\n // policy Skeleton follows and for the same reason — a wrapper here could\n // produce invalid markup (e.g. inside a <tr>/<li>) or break flex/grid\n // child layout. className/props only ever describe the spinning overlay\n // below, so there's nothing for them to apply to while idle.\n if (!spinning) {\n return children;\n }\n\n return (\n <div className={cn('relative', className)} {...props}>\n <div className=\"pointer-events-none opacity-50\">{children}</div>\n <div\n role=\"status\"\n aria-label=\"로딩 중\"\n className=\"absolute inset-0 flex items-center justify-center\"\n >\n <Loader2 className=\"animate-spin\" />\n </div>\n </div>\n );\n};\n\nexport default Spin;\n"],"mappings":";;;;;AAQA,MAAM,QAAQ,EAAE,UAAU,WAAW,UAAU,GAAG,YAAmB;AAInE,KAAI,CAAC,UAAU;AACb,MAAI,CAAC,SACH,QAAO;AAGT,SACE,oBAAC;GACC,MAAK;GACL,cAAW;GACX,WAAW,GAAG,2CAA2C,UAAU;GACnE,GAAI;aAEJ,oBAAC,WAAQ,WAAU,iBAAiB;IAChC;;AASV,KAAI,CAAC,SACH,QAAO;AAGT,QACE,qBAAC;EAAI,WAAW,GAAG,YAAY,UAAU;EAAE,GAAI;aAC7C,oBAAC;GAAI,WAAU;GAAkC;IAAe,EAChE,oBAAC;GACC,MAAK;GACL,cAAW;GACX,WAAU;aAEV,oBAAC,WAAQ,WAAU,iBAAiB;IAChC;GACF"}
1
+ {"version":3,"file":"spin.mjs","names":[],"sources":["../../../src/components/atoms/spin.tsx"],"sourcesContent":["'use client';\n\nimport { Loader2 } from 'lucide-react';\n\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn } from '@repo/ui/utils';\n\nexport interface Props extends React.ComponentPropsWithoutRef<'div'> {\n spinning?: boolean;\n}\n\nconst Spin = ({ spinning, className, children, ...props }: Props) => {\n const { locale } = useConfig();\n const loadingLabel = locale.loading ?? DEFAULT_LOCALE.loading;\n\n // With no children there's nothing to render at all while idle — unlike\n // the branch below, there's no wrapper for `className`/`props` to land\n // on regardless, so returning null here isn't the same bug.\n if (!children) {\n if (!spinning) {\n return null;\n }\n\n return (\n <div\n role=\"status\"\n aria-label={loadingLabel}\n className={cn('flex h-full items-center justify-center', className)}\n {...props}\n >\n <Loader2 className=\"animate-spin\" />\n </div>\n );\n }\n\n // Idle: return children as-is rather than inserting a wrapper div, same\n // policy Skeleton follows and for the same reason — a wrapper here could\n // produce invalid markup (e.g. inside a <tr>/<li>) or break flex/grid\n // child layout. className/props only ever describe the spinning overlay\n // below, so there's nothing for them to apply to while idle.\n if (!spinning) {\n return children;\n }\n\n return (\n <div className={cn('relative', className)} {...props}>\n <div className=\"pointer-events-none opacity-50\">{children}</div>\n <div\n role=\"status\"\n aria-label={loadingLabel}\n className=\"absolute inset-0 flex items-center justify-center\"\n >\n <Loader2 className=\"animate-spin\" />\n </div>\n </div>\n );\n};\n\nexport default Spin;\n"],"mappings":";;;;;;;;AAWA,MAAM,QAAQ,EAAE,UAAU,WAAW,UAAU,GAAG,YAAmB;CACnE,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,eAAe,OAAO,WAAW,eAAe;AAKtD,KAAI,CAAC,UAAU;AACb,MAAI,CAAC,SACH,QAAO;AAGT,SACE,oBAAC;GACC,MAAK;GACL,cAAY;GACZ,WAAW,GAAG,2CAA2C,UAAU;GACnE,GAAI;aAEJ,oBAAC,WAAQ,WAAU,iBAAiB;IAChC;;AASV,KAAI,CAAC,SACH,QAAO;AAGT,QACE,qBAAC;EAAI,WAAW,GAAG,YAAY,UAAU;EAAE,GAAI;aAC7C,oBAAC;GAAI,WAAU;GAAkC;IAAe,EAChE,oBAAC;GACC,MAAK;GACL,cAAY;GACZ,WAAU;aAEV,oBAAC,WAAQ,WAAU,iBAAiB;IAChC;GACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.d.mts","names":[],"sources":["../../../src/components/organisms/drawer.tsx"],"mappings":";;;UA0CiB,KAAA;EACf,IAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,QAAA;EACA,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,SAAA;EACA,IAAA;EACA,YAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,UAAA;IACE,IAAA;IACA,OAAA;IACA,SAAA;IACA,MAAA;IACA,KAAA;IACA,KAAA;IACA,KAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,SAAA,GAAY,WAAA;EACZ,OAAA;AAAA;AAAA,cA8BI,MAAA;EAAU,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,SAAA;EAAA,IAAA;EAAA,YAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,QAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAqBb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"drawer.d.mts","names":[],"sources":["../../../src/components/organisms/drawer.tsx"],"mappings":";;;UA2CiB,KAAA;EACf,IAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,QAAA;EACA,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,SAAA;EACA,IAAA;EACA,YAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,UAAA;IACE,IAAA;IACA,OAAA;IACA,SAAA;IACA,MAAA;IACA,KAAA;IACA,KAAA;IACA,KAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,SAAA,GAAY,WAAA;EACZ,OAAA;AAAA;AAAA,cA8BI,MAAA;EAAU,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,SAAA;EAAA,IAAA;EAAA,YAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,QAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAqBb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,6 +3,7 @@
3
3
  import { cn, renderConditional } from "../../utils.mjs";
4
4
  import { drawer_exports } from "../../core/drawer.mjs";
5
5
  import Button from "../../Button.mjs";
6
+ import { DEFAULT_LOCALE, useConfig } from "../../providers/Config/context.mjs";
6
7
  import { X } from "lucide-react";
7
8
  import { useEffect } from "react";
8
9
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -38,6 +39,7 @@ const getSizeStyles = (direction, size) => {
38
39
  return direction === "top" || direction === "bottom" ? { height: value } : { width: value };
39
40
  };
40
41
  const Drawer = ({ open, title, extra, footer, closable = true, closeIcon, direction = "bottom", size = "medium", maskClosable = true, handlebar = true, draggable = false, rounded = false, mask = true, className, classNames, style, children, container, onClose, ...props }) => {
42
+ const { locale } = useConfig();
41
43
  useEffect(() => {
42
44
  if (!open || mask) return;
43
45
  const targetDocument = container?.ownerDocument ?? document;
@@ -95,7 +97,7 @@ const Drawer = ({ open, title, extra, footer, closable = true, closeIcon, direct
95
97
  type: "text",
96
98
  shape: "circle",
97
99
  size: "small",
98
- "aria-label": "닫기",
100
+ "aria-label": locale.close ?? DEFAULT_LOCALE.close,
99
101
  icon: closeIcon || /* @__PURE__ */ jsx(X, {}),
100
102
  onClick: onClose,
101
103
  className: cn(classNames?.close)
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `body.style.pointerEvents` is global state (per document), so several\n// mask-less overlays opening at once would otherwise race: each instance\n// would capture whatever the previous one had already written and the\n// last cleanup would restore a stale value. Reference counting makes only\n// the first instance capture the original value and only the last one\n// restore it. Keyed by document (not a single module-level counter) so\n// drawers portaled into different documents — e.g. live-editor's iframe\n// Renderer — don't share state with the host document.\ntype MaskLessState = { count: number; originalPointerEvents: string | null };\nconst maskLessStates = new WeakMap<Document, MaskLessState>();\n\nconst getMaskLessState = (doc: Document): MaskLessState => {\n let state = maskLessStates.get(doc);\n\n if (!state) {\n state = { count: 0, originalPointerEvents: null };\n maskLessStates.set(doc, state);\n }\n\n return state;\n};\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\n// Rounds the edge facing into the viewport — the opposite edge from\n// whichever side the drawer is anchored to.\nconst ROUNDED_CLASSES: Record<'top' | 'bottom' | 'left' | 'right', string> = {\n top: 'rounded-b-[30px]!',\n bottom: 'rounded-t-[30px]!',\n left: 'rounded-r-[30px]!',\n right: 'rounded-l-[30px]!',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n const targetDocument = container?.ownerDocument ?? document;\n const targetWindow = targetDocument.defaultView ?? window;\n const body = targetDocument.body;\n const state = getMaskLessState(targetDocument);\n\n if (state.count === 0) {\n state.originalPointerEvents = body.style.pointerEvents;\n }\n state.count += 1;\n\n const raf = targetWindow.requestAnimationFrame(() => {\n body.style.pointerEvents = 'auto';\n });\n\n return () => {\n targetWindow.cancelAnimationFrame(raf);\n state.count -= 1;\n\n if (state.count === 0) {\n body.style.pointerEvents = state.originalPointerEvents ?? '';\n state.originalPointerEvents = null;\n }\n };\n }, [open, mask, container]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? ROUNDED_CLASSES[direction] : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {closable && (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label=\"닫기\"\n icon={closeIcon || <X />}\n onClick={onClose}\n className={cn(classNames?.close)}\n />\n )}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <DrawerTitle className={cn(classNames?.title)}>\n {title}\n </DrawerTitle>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n <DrawerDescription className=\"hidden\" />\n </DrawerHeader>\n <div\n className={cn(\n 'overflow-auto p-5',\n classNames?.body,\n //\n )}\n >\n {children}\n </div>\n {renderConditional(footer, v => (\n <DrawerFooter className={cn(classNames?.footer)}>{v}</DrawerFooter>\n ))}\n </DrawerContent>\n </DrawerCore>\n );\n};\n\nexport default Drawer;\n"],"mappings":";;;;;;;;;;AAWA,MAAM,EACJ,eACA,QAAQ,YACR,mBACA,cACA,cACA,gBACEA;AAWJ,MAAM,iCAAiB,IAAI,SAAkC;AAE7D,MAAM,oBAAoB,QAAiC;CACzD,IAAI,QAAQ,eAAe,IAAI,IAAI;AAEnC,KAAI,CAAC,OAAO;AACV,UAAQ;GAAE,OAAO;GAAG,uBAAuB;GAAM;AACjD,iBAAe,IAAI,KAAK,MAAM;;AAGhC,QAAO;;AAmCT,MAAM,QAAgC;CACpC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACP;AAID,MAAM,kBAAuE;CAC3E,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,MAAM,iBACJ,WACA,SACwB;CACxB,MAAM,QAAQ,MAAM,SAAS;AAE7B,QAAO,cAAc,SAAS,cAAc,WACxC,EAAE,QAAQ,OAAO,GACjB,EAAE,OAAO,OAAO;;AAGtB,MAAM,UAAU,EACd,MACA,OACA,OACA,QACA,WAAW,MACX,WACA,YAAY,UACZ,OAAO,UACP,eAAe,MACf,YAAY,MACZ,YAAY,OACZ,UAAU,OACV,OAAO,MACP,WACA,YACA,OACA,UACA,WACA,SACA,GAAG,YACQ;AACX,iBAAgB;AACd,MAAI,CAAC,QAAQ,KACX;EAGF,MAAM,iBAAiB,WAAW,iBAAiB;EACnD,MAAM,eAAe,eAAe,eAAe;EACnD,MAAM,OAAO,eAAe;EAC5B,MAAM,QAAQ,iBAAiB,eAAe;AAE9C,MAAI,MAAM,UAAU,EAClB,OAAM,wBAAwB,KAAK,MAAM;AAE3C,QAAM,SAAS;EAEf,MAAM,MAAM,aAAa,4BAA4B;AACnD,QAAK,MAAM,gBAAgB;IAC3B;AAEF,eAAa;AACX,gBAAa,qBAAqB,IAAI;AACtC,SAAM,SAAS;AAEf,OAAI,MAAM,UAAU,GAAG;AACrB,SAAK,MAAM,gBAAgB,MAAM,yBAAyB;AAC1D,UAAM,wBAAwB;;;IAGjC;EAAC;EAAM;EAAM;EAAU,CAAC;AAE3B,QACE,oBAAC;EACO;EACK;EACX,YAAY,CAAC;EACF;EACX,eAAc,SAAQ;AACpB,OAAI,CAAC,KACH,UAAS;;EAGb,GAAI;YAEJ,qBAAC;GACC,WAAW,GACT,4BACA,UAAU,gBAAgB,aAAa,iBACvC,YAAY,SACZ,UAED;GACU;GACL;GACN,uBAAsB,UAAS;AAC7B,QAAI,CAAC,aACH,OAAM,gBAAgB;;GAG1B,YAAY;IACV,MAAM,YAAY,QAAQ;IAC1B,WAAW,YAAY,aAAa;IACrC;GACD,OAAO;IACL,GAAG,cAAc,WAAW,KAAK;IACjC,GAAG;IACJ;;IAED,qBAAC;KACC,WAAW,GACT,YAAY,QACZ,CAAC,SAAS,MAEX;gBAED,qBAAC;MAAI,WAAU;iBACZ,YACC,oBAAC;OACC,MAAK;OACL,OAAM;OACN,MAAK;OACL,cAAW;OACX,MAAM,aAAa,oBAAC,MAAI;OACxB,SAAS;OACT,WAAW,GAAG,YAAY,MAAM;QAChC,EAEJ,qBAAC;OAAI,WAAU;kBACb,oBAAC;QAAY,WAAW,GAAG,YAAY,MAAM;kBAC1C;SACW,EACb,kBAAkB,QAAO,MACxB,oBAAC;QAAI,WAAW,GAAG,YAAY,YAAY,MAAM;kBAAG;SAAQ,CAC5D;QACE;OACF,EACN,oBAAC,qBAAkB,WAAU,WAAW;MAC3B;IACf,oBAAC;KACC,WAAW,GACT,qBACA,YAAY,KAEb;KAEA;MACG;IACL,kBAAkB,SAAQ,MACzB,oBAAC;KAAa,WAAW,GAAG,YAAY,OAAO;eAAG;MAAiB,CACnE;;IACY;GACL"}
1
+ {"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { DEFAULT_LOCALE, useConfig } from '@repo/ui/providers';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `body.style.pointerEvents` is global state (per document), so several\n// mask-less overlays opening at once would otherwise race: each instance\n// would capture whatever the previous one had already written and the\n// last cleanup would restore a stale value. Reference counting makes only\n// the first instance capture the original value and only the last one\n// restore it. Keyed by document (not a single module-level counter) so\n// drawers portaled into different documents — e.g. live-editor's iframe\n// Renderer — don't share state with the host document.\ntype MaskLessState = { count: number; originalPointerEvents: string | null };\nconst maskLessStates = new WeakMap<Document, MaskLessState>();\n\nconst getMaskLessState = (doc: Document): MaskLessState => {\n let state = maskLessStates.get(doc);\n\n if (!state) {\n state = { count: 0, originalPointerEvents: null };\n maskLessStates.set(doc, state);\n }\n\n return state;\n};\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\n// Rounds the edge facing into the viewport — the opposite edge from\n// whichever side the drawer is anchored to.\nconst ROUNDED_CLASSES: Record<'top' | 'bottom' | 'left' | 'right', string> = {\n top: 'rounded-b-[30px]!',\n bottom: 'rounded-t-[30px]!',\n left: 'rounded-r-[30px]!',\n right: 'rounded-l-[30px]!',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n const { locale } = useConfig();\n\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n const targetDocument = container?.ownerDocument ?? document;\n const targetWindow = targetDocument.defaultView ?? window;\n const body = targetDocument.body;\n const state = getMaskLessState(targetDocument);\n\n if (state.count === 0) {\n state.originalPointerEvents = body.style.pointerEvents;\n }\n state.count += 1;\n\n const raf = targetWindow.requestAnimationFrame(() => {\n body.style.pointerEvents = 'auto';\n });\n\n return () => {\n targetWindow.cancelAnimationFrame(raf);\n state.count -= 1;\n\n if (state.count === 0) {\n body.style.pointerEvents = state.originalPointerEvents ?? '';\n state.originalPointerEvents = null;\n }\n };\n }, [open, mask, container]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? ROUNDED_CLASSES[direction] : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {closable && (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label={locale.close ?? DEFAULT_LOCALE.close}\n icon={closeIcon || <X />}\n onClick={onClose}\n className={cn(classNames?.close)}\n />\n )}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <DrawerTitle className={cn(classNames?.title)}>\n {title}\n </DrawerTitle>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n <DrawerDescription className=\"hidden\" />\n </DrawerHeader>\n <div\n className={cn(\n 'overflow-auto p-5',\n classNames?.body,\n //\n )}\n >\n {children}\n </div>\n {renderConditional(footer, v => (\n <DrawerFooter className={cn(classNames?.footer)}>{v}</DrawerFooter>\n ))}\n </DrawerContent>\n </DrawerCore>\n );\n};\n\nexport default Drawer;\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,EACJ,eACA,QAAQ,YACR,mBACA,cACA,cACA,gBACEA;AAWJ,MAAM,iCAAiB,IAAI,SAAkC;AAE7D,MAAM,oBAAoB,QAAiC;CACzD,IAAI,QAAQ,eAAe,IAAI,IAAI;AAEnC,KAAI,CAAC,OAAO;AACV,UAAQ;GAAE,OAAO;GAAG,uBAAuB;GAAM;AACjD,iBAAe,IAAI,KAAK,MAAM;;AAGhC,QAAO;;AAmCT,MAAM,QAAgC;CACpC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACP;AAID,MAAM,kBAAuE;CAC3E,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAED,MAAM,iBACJ,WACA,SACwB;CACxB,MAAM,QAAQ,MAAM,SAAS;AAE7B,QAAO,cAAc,SAAS,cAAc,WACxC,EAAE,QAAQ,OAAO,GACjB,EAAE,OAAO,OAAO;;AAGtB,MAAM,UAAU,EACd,MACA,OACA,OACA,QACA,WAAW,MACX,WACA,YAAY,UACZ,OAAO,UACP,eAAe,MACf,YAAY,MACZ,YAAY,OACZ,UAAU,OACV,OAAO,MACP,WACA,YACA,OACA,UACA,WACA,SACA,GAAG,YACQ;CACX,MAAM,EAAE,WAAW,WAAW;AAE9B,iBAAgB;AACd,MAAI,CAAC,QAAQ,KACX;EAGF,MAAM,iBAAiB,WAAW,iBAAiB;EACnD,MAAM,eAAe,eAAe,eAAe;EACnD,MAAM,OAAO,eAAe;EAC5B,MAAM,QAAQ,iBAAiB,eAAe;AAE9C,MAAI,MAAM,UAAU,EAClB,OAAM,wBAAwB,KAAK,MAAM;AAE3C,QAAM,SAAS;EAEf,MAAM,MAAM,aAAa,4BAA4B;AACnD,QAAK,MAAM,gBAAgB;IAC3B;AAEF,eAAa;AACX,gBAAa,qBAAqB,IAAI;AACtC,SAAM,SAAS;AAEf,OAAI,MAAM,UAAU,GAAG;AACrB,SAAK,MAAM,gBAAgB,MAAM,yBAAyB;AAC1D,UAAM,wBAAwB;;;IAGjC;EAAC;EAAM;EAAM;EAAU,CAAC;AAE3B,QACE,oBAAC;EACO;EACK;EACX,YAAY,CAAC;EACF;EACX,eAAc,SAAQ;AACpB,OAAI,CAAC,KACH,UAAS;;EAGb,GAAI;YAEJ,qBAAC;GACC,WAAW,GACT,4BACA,UAAU,gBAAgB,aAAa,iBACvC,YAAY,SACZ,UAED;GACU;GACL;GACN,uBAAsB,UAAS;AAC7B,QAAI,CAAC,aACH,OAAM,gBAAgB;;GAG1B,YAAY;IACV,MAAM,YAAY,QAAQ;IAC1B,WAAW,YAAY,aAAa;IACrC;GACD,OAAO;IACL,GAAG,cAAc,WAAW,KAAK;IACjC,GAAG;IACJ;;IAED,qBAAC;KACC,WAAW,GACT,YAAY,QACZ,CAAC,SAAS,MAEX;gBAED,qBAAC;MAAI,WAAU;iBACZ,YACC,oBAAC;OACC,MAAK;OACL,OAAM;OACN,MAAK;OACL,cAAY,OAAO,SAAS,eAAe;OAC3C,MAAM,aAAa,oBAAC,MAAI;OACxB,SAAS;OACT,WAAW,GAAG,YAAY,MAAM;QAChC,EAEJ,qBAAC;OAAI,WAAU;kBACb,oBAAC;QAAY,WAAW,GAAG,YAAY,MAAM;kBAC1C;SACW,EACb,kBAAkB,QAAO,MACxB,oBAAC;QAAI,WAAW,GAAG,YAAY,YAAY,MAAM;kBAAG;SAAQ,CAC5D;QACE;OACF,EACN,oBAAC,qBAAkB,WAAU,WAAW;MAC3B;IACf,oBAAC;KACC,WAAW,GACT,qBACA,YAAY,KAEb;KAEA;MACG;IACL,kBAAkB,SAAQ,MACzB,oBAAC;KAAa,WAAW,GAAG,YAAY,OAAO;eAAG;MAAiB,CACnE;;IACY;GACL"}
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState } from "react";
4
+ import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
5
+ import { v4 } from "uuid";
6
+ import { createRoot } from "react-dom/client";
7
+
8
+ //#region src/components/organisms/imperative-stack.tsx
9
+ const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
10
+ function createImperativeStack({ createRootElement, StackItem }) {
11
+ const containerStates = /* @__PURE__ */ new Map();
12
+ const rootElements = /* @__PURE__ */ new WeakMap();
13
+ const reactRoots = /* @__PURE__ */ new Map();
14
+ const getContainerState = (container) => {
15
+ let state = containerStates.get(container);
16
+ if (!state) {
17
+ state = {
18
+ stack: [],
19
+ update: null
20
+ };
21
+ containerStates.set(container, state);
22
+ }
23
+ return state;
24
+ };
25
+ const getRootElement = (container) => {
26
+ if (!isBrowser) return null;
27
+ const targetContainer = container || document.body;
28
+ let rootEl = rootElements.get(targetContainer);
29
+ if (!rootEl) {
30
+ rootEl = createRootElement();
31
+ targetContainer.appendChild(rootEl);
32
+ rootElements.set(targetContainer, rootEl);
33
+ }
34
+ return rootEl;
35
+ };
36
+ const StackRenderer = ({ container }) => {
37
+ const [, forceUpdate] = useState({});
38
+ useEffect(() => {
39
+ const state = getContainerState(container);
40
+ state.update = () => forceUpdate({});
41
+ return () => {
42
+ state.update = null;
43
+ };
44
+ }, [container]);
45
+ const { stack } = getContainerState(container);
46
+ return /* @__PURE__ */ jsx(Fragment$1, { children: stack.map(({ id, ...props }) => /* @__PURE__ */ jsx(StackItem, {
47
+ id,
48
+ ...props
49
+ }, id)) });
50
+ };
51
+ const render = (props) => {
52
+ if (!isBrowser) return;
53
+ const targetContainer = props.container || document.body;
54
+ const rootElement = getRootElement(targetContainer);
55
+ if (!reactRoots.has(targetContainer)) {
56
+ const root = createRoot(rootElement);
57
+ reactRoots.set(targetContainer, root);
58
+ root.render(/* @__PURE__ */ jsx(StackRenderer, { container: targetContainer }));
59
+ }
60
+ const state = getContainerState(targetContainer);
61
+ const id = props.id || v4();
62
+ state.stack.push({
63
+ ...props,
64
+ id
65
+ });
66
+ state.update?.();
67
+ return id;
68
+ };
69
+ const destroy = (id) => {
70
+ if (!id) {
71
+ containerStates.forEach((state) => {
72
+ state.stack = [];
73
+ state.update?.();
74
+ });
75
+ reactRoots.forEach((root, container) => {
76
+ root.unmount();
77
+ rootElements.get(container)?.remove();
78
+ rootElements.delete(container);
79
+ });
80
+ reactRoots.clear();
81
+ containerStates.clear();
82
+ return;
83
+ }
84
+ containerStates.forEach((state, container) => {
85
+ if (!state.stack.some((item) => item.id === id)) return;
86
+ state.stack = state.stack.filter((item) => item.id !== id);
87
+ state.update?.();
88
+ if (!state.stack.length) {
89
+ reactRoots.get(container)?.unmount();
90
+ reactRoots.delete(container);
91
+ containerStates.delete(container);
92
+ rootElements.get(container)?.remove();
93
+ rootElements.delete(container);
94
+ }
95
+ });
96
+ };
97
+ return {
98
+ render,
99
+ destroy,
100
+ getRootElement
101
+ };
102
+ }
103
+
104
+ //#endregion
105
+ export { createImperativeStack, isBrowser };
106
+ //# sourceMappingURL=imperative-stack.mjs.map
@@ -0,0 +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\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 const getRootElement = (container?: HTMLElement): HTMLElement | null => {\n if (!isBrowser) {\n return null;\n }\n\n const targetContainer = container || document.body;\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 <>\n {stack.map(({ id, ...props }) => (\n <StackItem key={id} id={id} {...(props as TProps)} />\n ))}\n </>\n );\n };\n\n const render = (props: TProps): string | undefined => {\n if (!isBrowser) {\n return;\n }\n\n const targetContainer = props.container || document.body;\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":";;;;;;;;AAeA,MAAa,YACX,OAAO,WAAW,eAAe,OAAO,aAAa;AA2BvD,SAAgB,sBAEd,EACA,mBACA,aAC0D;CAC1D,MAAM,kCAAkB,IAAI,KAA0C;CACtE,MAAM,+BAAe,IAAI,SAAmC;CAC5D,MAAM,6BAAa,IAAI,KAAwB;CAE/C,MAAM,qBACJ,cAC2B;EAC3B,IAAI,QAAQ,gBAAgB,IAAI,UAAU;AAE1C,MAAI,CAAC,OAAO;AACV,WAAQ;IAAE,OAAO,EAAE;IAAE,QAAQ;IAAM;AACnC,mBAAgB,IAAI,WAAW,MAAM;;AAGvC,SAAO;;CAGT,MAAM,kBAAkB,cAAgD;AACtE,MAAI,CAAC,UACH,QAAO;EAGT,MAAM,kBAAkB,aAAa,SAAS;EAC9C,IAAI,SAAS,aAAa,IAAI,gBAAgB;AAE9C,MAAI,CAAC,QAAQ;AACX,YAAS,mBAAmB;AAC5B,mBAAgB,YAAY,OAAO;AACnC,gBAAa,IAAI,iBAAiB,OAAO;;AAG3C,SAAO;;CAGT,MAAM,iBAAiB,EAAE,gBAA4C;EACnE,MAAM,GAAG,eAAe,SAAS,EAAE,CAAC;AAEpC,kBAAgB;GACd,MAAM,QAAQ,kBAAkB,UAAU;AAC1C,SAAM,eAAe,YAAY,EAAE,CAAC;AACpC,gBAAa;AACX,UAAM,SAAS;;KAEhB,CAAC,UAAU,CAAC;EAEf,MAAM,EAAE,UAAU,kBAAkB,UAAU;AAE9C,SACE,4CACG,MAAM,KAAK,EAAE,IAAI,GAAG,YACnB,oBAAC;GAAuB;GAAI,GAAK;KAAjB,GAAqC,CACrD,GACD;;CAIP,MAAM,UAAU,UAAsC;AACpD,MAAI,CAAC,UACH;EAGF,MAAM,kBAAkB,MAAM,aAAa,SAAS;EACpD,MAAM,cAAc,eAAe,gBAAgB;AAEnD,MAAI,CAAC,WAAW,IAAI,gBAAgB,EAAE;GACpC,MAAM,OAAO,WAAW,YAAY;AACpC,cAAW,IAAI,iBAAiB,KAAK;AACrC,QAAK,OAAO,oBAAC,iBAAc,WAAW,kBAAmB,CAAC;;EAG5D,MAAM,QAAQ,kBAAkB,gBAAgB;EAChD,MAAM,KAAK,MAAM,MAAMA,IAAM;AAC7B,QAAM,MAAM,KAAK;GAAE,GAAG;GAAO;GAAI,CAAC;AAClC,QAAM,UAAU;AAEhB,SAAO;;CAGT,MAAM,WAAW,OAAgB;AAC/B,MAAI,CAAC,IAAI;AACP,mBAAgB,SAAQ,UAAS;AAC/B,UAAM,QAAQ,EAAE;AAChB,UAAM,UAAU;KAChB;AACF,cAAW,SAAS,MAAM,cAAc;AACtC,SAAK,SAAS;AACd,iBAAa,IAAI,UAAU,EAAE,QAAQ;AACrC,iBAAa,OAAO,UAAU;KAC9B;AACF,cAAW,OAAO;AAClB,mBAAgB,OAAO;AACvB;;AAGF,kBAAgB,SAAS,OAAO,cAAc;AAC5C,OAAI,CAAC,MAAM,MAAM,MAAK,SAAQ,KAAK,OAAO,GAAG,CAC3C;AAGF,SAAM,QAAQ,MAAM,MAAM,QAAO,SAAQ,KAAK,OAAO,GAAG;AACxD,SAAM,UAAU;AAEhB,OAAI,CAAC,MAAM,MAAM,QAAQ;AACvB,eAAW,IAAI,UAAU,EAAE,SAAS;AACpC,eAAW,OAAO,UAAU;AAC5B,oBAAgB,OAAO,UAAU;AACjC,iBAAa,IAAI,UAAU,EAAE,QAAQ;AACrC,iBAAa,OAAO,UAAU;;IAEhC;;AAGJ,QAAO;EAAE;EAAQ;EAAS;EAAgB"}
@@ -1,5 +1,7 @@
1
1
  import { Drawer, Props } from "./drawer.mjs";
2
+ import { Props as Props$1 } from "./list/list.mjs";
2
3
  import { List } from "./list/index.mjs";
3
- import { Modal } from "./modal.mjs";
4
+ import { Modal, Props as Props$2 } from "./modal.mjs";
5
+ import { Props as Props$3 } from "./swiper/swiper.mjs";
4
6
  import { Swiper } from "./swiper/index.mjs";
5
7
  import { StaticProps, Toast } from "./toast.mjs";
@@ -1,5 +1,5 @@
1
1
  import { Item } from "./item.mjs";
2
- import { List as List$1 } from "./list.mjs";
2
+ import { List as List$1, Props } from "./list.mjs";
3
3
 
4
4
  //#region src/components/organisms/list/index.d.ts
5
5
  type ListComponent = typeof List$1 & {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["ListImpl"],"sources":["../../../../src/components/organisms/list/index.ts"],"sourcesContent":["import Item from './item';\nimport ListImpl from './list';\n\ntype ListComponent = typeof ListImpl & { Item: typeof Item };\n\nconst List = ListImpl as ListComponent;\n\nList.Item = Item;\n\nexport default List;\n"],"mappings":";;;;AAKA,MAAM,OAAOA;AAEb,KAAK,OAAO"}
1
+ {"version":3,"file":"index.mjs","names":["ListImpl"],"sources":["../../../../src/components/organisms/list/index.ts"],"sourcesContent":["import Item from './item';\nimport ListImpl from './list';\n\ntype ListComponent = typeof ListImpl & { Item: typeof Item };\n\nconst List = ListImpl as ListComponent;\n\nList.Item = Item;\n\nexport default List;\nexport type { Props as ListProps } from './list';\n"],"mappings":";;;;AAKA,MAAM,OAAOA;AAEb,KAAK,OAAO"}
@@ -49,7 +49,7 @@ declare const List: <T>({
49
49
  renderItem,
50
50
  itemKey,
51
51
  ...props
52
- }: Props<T>) => string | number | bigint | true | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | react_jsx_runtime0.JSX.Element;
52
+ }: Props<T>) => react_jsx_runtime0.JSX.Element;
53
53
  //#endregion
54
- export { List };
54
+ export { List, Props };
55
55
  //# sourceMappingURL=list.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.mts","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"mappings":";;;;;UAWU,KAAA,YAAiB,IAAA,CACzB,KAAA,CAAM,wBAAA;EAGN,OAAA;EACA,WAAA,GAAc,KAAA,CAAM,cAAA,QAAsB,QAAA;EAC1C,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,UAAA;EACA,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,UAAA;IACE,KAAA;IACA,MAAA;IACA,IAAA;EAAA;EAEF,MAAA;IACE,OAAA;IACA,OAAA;IACA,MAAA,GAAS,KAAA,CAAM,SAAA;IACf,OAAA,GAAU,wBAAA;IAYK;;;;;;;IAJf,IAAA;EAAA;EAEF,IAAA,GAAO,CAAA;EACP,UAAA,IAAc,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,KAAA,CAAM,SAAA;EAC/C,OAAA,IAAW,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,KAAA,CAAM,GAAA;AAAA;AAAA,cAGxC,IAAA;EAAY,OAAA;EAAA,WAAA;EAAA,MAAA;EAAA,MAAA;EAAA,KAAA;EAAA,UAAA;EAAA,KAAA;EAAA,MAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,UAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAef,KAAA,CAAM,CAAA,wCAAE,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA,wBAAA,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"list.d.mts","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"mappings":";;;;;UAWiB,KAAA,YAAiB,IAAA,CAChC,KAAA,CAAM,wBAAA;EAGN,OAAA;EACA,WAAA,GAAc,KAAA,CAAM,cAAA,QAAsB,QAAA;EAC1C,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,UAAA;EACA,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,UAAA;IACE,KAAA;IACA,MAAA;IACA,IAAA;EAAA;EAEF,MAAA;IACE,OAAA;IACA,OAAA;IACA,MAAA,GAAS,KAAA,CAAM,SAAA;IACf,OAAA,GAAU,wBAAA;IAYK;;;;;;;IAJf,IAAA;EAAA;EAEF,IAAA,GAAO,CAAA;EACP,UAAA,IAAc,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,KAAA,CAAM,SAAA;EAC/C,OAAA,IAAW,IAAA,EAAM,CAAA,EAAG,KAAA,aAAkB,KAAA,CAAM,GAAA;AAAA;AAAA,cAGxC,IAAA;EAAY,OAAA;EAAA,WAAA;EAAA,MAAA;EAAA,MAAA;EAAA,KAAA;EAAA,UAAA;EAAA,KAAA;EAAA,MAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,UAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAef,KAAA,CAAM,CAAA,MAAE,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -4,7 +4,7 @@ import { cn, renderConditional } from "../../../utils.mjs";
4
4
  import Title from "../../atoms/typography/title.mjs";
5
5
  import Skeleton from "../../atoms/skeleton/index.mjs";
6
6
  import React, { useEffect, useRef } from "react";
7
- import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useIntersectionObserver } from "@jbpark/use-hooks";
9
9
 
10
10
  //#region src/components/organisms/list/list.tsx
@@ -27,10 +27,10 @@ const List = ({ loading, loaderProps, loader, header, title, titleLevel = 2, emp
27
27
  scroll.next();
28
28
  }
29
29
  }, [isIntersecting, scroll]);
30
- if (loading) return loader || /* @__PURE__ */ jsxs("div", {
30
+ if (loading) return /* @__PURE__ */ jsx("div", {
31
31
  className: cn(className),
32
32
  ...props,
33
- children: [
33
+ children: loader ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
34
34
  /* @__PURE__ */ jsx("div", {
35
35
  className: cn(classNames?.title),
36
36
  children: title && /* @__PURE__ */ jsx(Skeleton, {})
@@ -47,7 +47,7 @@ const List = ({ loading, loaderProps, loader, header, title, titleLevel = 2, emp
47
47
  ...loaderProps
48
48
  })
49
49
  })
50
- ]
50
+ ] })
51
51
  });
52
52
  return /* @__PURE__ */ jsxs("div", {
53
53
  className: cn(className),
@@ -66,13 +66,22 @@ const List = ({ loading, loaderProps, loader, header, title, titleLevel = 2, emp
66
66
  role: "list",
67
67
  className: cn("space-y-2", classNames?.body),
68
68
  children: [
69
- !data?.length && empty ? empty : data?.map((item, i) => /* @__PURE__ */ jsx(React.Fragment, { children: renderItem(item, i) }, itemKey ? itemKey(item, i) : i)),
70
- scroll?.loading && (scroll?.loader ?? /* @__PURE__ */ jsx(Skeleton.Node, {
71
- count: 10,
72
- gap: 10,
73
- ...loaderProps
74
- })),
75
- scroll && /* @__PURE__ */ jsx("div", { ref: loaderRef })
69
+ !data?.length && empty ? empty : data?.map((item, i) => /* @__PURE__ */ jsx("div", {
70
+ role: "listitem",
71
+ children: renderItem(item, i)
72
+ }, itemKey ? itemKey(item, i) : i)),
73
+ scroll?.loading && /* @__PURE__ */ jsx("div", {
74
+ role: "presentation",
75
+ children: scroll?.loader ?? /* @__PURE__ */ jsx(Skeleton.Node, {
76
+ count: 10,
77
+ gap: 10,
78
+ ...loaderProps
79
+ })
80
+ }),
81
+ scroll && /* @__PURE__ */ jsx("div", {
82
+ ref: loaderRef,
83
+ role: "none"
84
+ })
76
85
  ]
77
86
  })
78
87
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"list.mjs","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useRef } from 'react';\n\nimport { useIntersectionObserver } from '@jbpark/use-hooks';\n\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Skeleton from '../../atoms/skeleton';\nimport { Title } from '../../atoms/typography';\n\ninterface Props<T> extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title'\n> {\n loading?: boolean;\n loaderProps?: React.ComponentProps<typeof Skeleton>;\n loader?: React.ReactNode;\n title?: React.ReactNode;\n titleLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n header?: React.ReactNode;\n empty?: React.ReactNode;\n classNames?: {\n title?: string;\n header?: string;\n body?: string;\n };\n scroll?: {\n hasMore: boolean;\n loading: boolean;\n loader?: React.ReactNode;\n options?: IntersectionObserverInit;\n /**\n * Called when more items should be fetched. `List` tracks in-flight\n * requests via `loading` — the caller MUST flip `loading` back to\n * `false` when the fetch settles, including on failure/rejection.\n * If `loading` never becomes `false` again after a failed fetch,\n * `List` will stop calling `next()` for subsequent intersections.\n */\n next: () => void;\n };\n data?: T[];\n renderItem?: (item: T, index: number) => React.ReactNode;\n itemKey?: (item: T, index: number) => React.Key;\n}\n\nconst List = <T,>({\n loading,\n loaderProps,\n loader,\n header,\n title,\n titleLevel = 2,\n empty,\n scroll,\n data,\n className,\n classNames,\n renderItem = () => null,\n itemKey,\n ...props\n}: Props<T>) => {\n const [loaderRef, { isIntersecting }] = useIntersectionObserver({\n threshold: 0,\n root: null,\n rootMargin: '0px',\n ...scroll?.options,\n });\n\n // `scroll` is typically a new object identity every render, so this\n // effect re-runs often. Guard with a ref (updated synchronously, unlike\n // the `loading` prop which only reflects the caller's next state update)\n // to avoid firing `next()` again for the same in-flight request before\n // the caller's `loading` has had a chance to become true.\n const fetchingRef = useRef(false);\n\n useEffect(() => {\n if (!scroll) {\n return;\n }\n\n if (scroll.loading) {\n fetchingRef.current = false;\n return;\n }\n\n if (isIntersecting && scroll.hasMore && !fetchingRef.current) {\n fetchingRef.current = true;\n scroll.next();\n }\n }, [isIntersecting, scroll]);\n\n if (loading) {\n return (\n loader || (\n <div className={cn(className)} {...props}>\n <div className={cn(classNames?.title)}>{title && <Skeleton />}</div>\n <div className={cn(classNames?.header)}>\n {header && <Skeleton size=\"small\" />}\n </div>\n <div className={cn('space-y-2', classNames?.body)}>\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n </div>\n </div>\n )\n );\n }\n\n return (\n <div\n className={cn(\n className,\n //\n )}\n {...props}\n >\n {renderConditional(title, v => (\n <Title\n level={titleLevel}\n className={cn(\n 'px-1.5 py-4',\n 'text-black-90 text-lg leading-5.75 font-bold',\n //\n )}\n >\n {v}\n </Title>\n ))}\n <div className={cn(classNames?.header)}>{header}</div>\n <div role=\"list\" className={cn('space-y-2', classNames?.body)}>\n {!data?.length && empty\n ? empty\n : data?.map((item, i) => (\n <React.Fragment key={itemKey ? itemKey(item, i) : i}>\n {renderItem(item, i)}\n </React.Fragment>\n ))}\n {scroll?.loading &&\n (scroll?.loader ?? (\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n ))}\n {scroll && <div ref={loaderRef} />}\n </div>\n </div>\n );\n};\n\nexport default List;\n"],"mappings":";;;;;;;;;;AA8CA,MAAM,QAAY,EAChB,SACA,aACA,QACA,QACA,OACA,aAAa,GACb,OACA,QACA,MACA,WACA,YACA,mBAAmB,MACnB,SACA,GAAG,YACW;CACd,MAAM,CAAC,WAAW,EAAE,oBAAoB,wBAAwB;EAC9D,WAAW;EACX,MAAM;EACN,YAAY;EACZ,GAAG,QAAQ;EACZ,CAAC;CAOF,MAAM,cAAc,OAAO,MAAM;AAEjC,iBAAgB;AACd,MAAI,CAAC,OACH;AAGF,MAAI,OAAO,SAAS;AAClB,eAAY,UAAU;AACtB;;AAGF,MAAI,kBAAkB,OAAO,WAAW,CAAC,YAAY,SAAS;AAC5D,eAAY,UAAU;AACtB,UAAO,MAAM;;IAEd,CAAC,gBAAgB,OAAO,CAAC;AAE5B,KAAI,QACF,QACE,UACE,qBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;;GACjC,oBAAC;IAAI,WAAW,GAAG,YAAY,MAAM;cAAG,SAAS,oBAAC,aAAW;KAAO;GACpE,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cACnC,UAAU,oBAAC,YAAS,MAAK,UAAU;KAChC;GACN,oBAAC;IAAI,WAAW,GAAG,aAAa,YAAY,KAAK;cAC/C,oBAAC,SAAS;KAAK,OAAO;KAAI,KAAK;KAAI,GAAI;MAAe;KAClD;;GACF;AAKZ,QACE,qBAAC;EACC,WAAW,GACT,UAED;EACD,GAAI;;GAEH,kBAAkB,QAAO,MACxB,oBAAC;IACC,OAAO;IACP,WAAW,GACT,eACA,+CAED;cAEA;KACK,CACR;GACF,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cAAG;KAAa;GACtD,qBAAC;IAAI,MAAK;IAAO,WAAW,GAAG,aAAa,YAAY,KAAK;;KAC1D,CAAC,MAAM,UAAU,QACd,QACA,MAAM,KAAK,MAAM,MACf,oBAAC,MAAM,sBACJ,WAAW,MAAM,EAAE,IADD,UAAU,QAAQ,MAAM,EAAE,GAAG,EAEjC,CACjB;KACL,QAAQ,YACN,QAAQ,UACP,oBAAC,SAAS;MAAK,OAAO;MAAI,KAAK;MAAI,GAAI;OAAe;KAEzD,UAAU,oBAAC,SAAI,KAAK,YAAa;;KAC9B;;GACF"}
1
+ {"version":3,"file":"list.mjs","names":[],"sources":["../../../../src/components/organisms/list/list.tsx"],"sourcesContent":["'use client';\n\nimport React, { useEffect, useRef } from 'react';\n\nimport { useIntersectionObserver } from '@jbpark/use-hooks';\n\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Skeleton from '../../atoms/skeleton';\nimport { Title } from '../../atoms/typography';\n\nexport interface Props<T> extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title'\n> {\n loading?: boolean;\n loaderProps?: React.ComponentProps<typeof Skeleton>;\n loader?: React.ReactNode;\n title?: React.ReactNode;\n titleLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n header?: React.ReactNode;\n empty?: React.ReactNode;\n classNames?: {\n title?: string;\n header?: string;\n body?: string;\n };\n scroll?: {\n hasMore: boolean;\n loading: boolean;\n loader?: React.ReactNode;\n options?: IntersectionObserverInit;\n /**\n * Called when more items should be fetched. `List` tracks in-flight\n * requests via `loading` — the caller MUST flip `loading` back to\n * `false` when the fetch settles, including on failure/rejection.\n * If `loading` never becomes `false` again after a failed fetch,\n * `List` will stop calling `next()` for subsequent intersections.\n */\n next: () => void;\n };\n data?: T[];\n renderItem?: (item: T, index: number) => React.ReactNode;\n itemKey?: (item: T, index: number) => React.Key;\n}\n\nconst List = <T,>({\n loading,\n loaderProps,\n loader,\n header,\n title,\n titleLevel = 2,\n empty,\n scroll,\n data,\n className,\n classNames,\n renderItem = () => null,\n itemKey,\n ...props\n}: Props<T>) => {\n const [loaderRef, { isIntersecting }] = useIntersectionObserver({\n threshold: 0,\n root: null,\n rootMargin: '0px',\n ...scroll?.options,\n });\n\n // `scroll` is typically a new object identity every render, so this\n // effect re-runs often. Guard with a ref (updated synchronously, unlike\n // the `loading` prop which only reflects the caller's next state update)\n // to avoid firing `next()` again for the same in-flight request before\n // the caller's `loading` has had a chance to become true.\n const fetchingRef = useRef(false);\n\n useEffect(() => {\n if (!scroll) {\n return;\n }\n\n if (scroll.loading) {\n fetchingRef.current = false;\n return;\n }\n\n if (isIntersecting && scroll.hasMore && !fetchingRef.current) {\n fetchingRef.current = true;\n scroll.next();\n }\n }, [isIntersecting, scroll]);\n\n if (loading) {\n return (\n <div className={cn(className)} {...props}>\n {loader ?? (\n <>\n <div className={cn(classNames?.title)}>{title && <Skeleton />}</div>\n <div className={cn(classNames?.header)}>\n {header && <Skeleton size=\"small\" />}\n </div>\n <div className={cn('space-y-2', classNames?.body)}>\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n </div>\n </>\n )}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n className,\n //\n )}\n {...props}\n >\n {renderConditional(title, v => (\n <Title\n level={titleLevel}\n className={cn(\n 'px-1.5 py-4',\n 'text-black-90 text-lg leading-5.75 font-bold',\n //\n )}\n >\n {v}\n </Title>\n ))}\n <div className={cn(classNames?.header)}>{header}</div>\n <div role=\"list\" className={cn('space-y-2', classNames?.body)}>\n {!data?.length && empty\n ? empty\n : data?.map((item, i) => (\n <div role=\"listitem\" key={itemKey ? itemKey(item, i) : i}>\n {renderItem(item, i)}\n </div>\n ))}\n {scroll?.loading && (\n <div role=\"presentation\">\n {scroll?.loader ?? (\n <Skeleton.Node count={10} gap={10} {...loaderProps} />\n )}\n </div>\n )}\n {scroll && <div ref={loaderRef} role=\"none\" />}\n </div>\n </div>\n );\n};\n\nexport default List;\n"],"mappings":";;;;;;;;;;AA8CA,MAAM,QAAY,EAChB,SACA,aACA,QACA,QACA,OACA,aAAa,GACb,OACA,QACA,MACA,WACA,YACA,mBAAmB,MACnB,SACA,GAAG,YACW;CACd,MAAM,CAAC,WAAW,EAAE,oBAAoB,wBAAwB;EAC9D,WAAW;EACX,MAAM;EACN,YAAY;EACZ,GAAG,QAAQ;EACZ,CAAC;CAOF,MAAM,cAAc,OAAO,MAAM;AAEjC,iBAAgB;AACd,MAAI,CAAC,OACH;AAGF,MAAI,OAAO,SAAS;AAClB,eAAY,UAAU;AACtB;;AAGF,MAAI,kBAAkB,OAAO,WAAW,CAAC,YAAY,SAAS;AAC5D,eAAY,UAAU;AACtB,UAAO,MAAM;;IAEd,CAAC,gBAAgB,OAAO,CAAC;AAE5B,KAAI,QACF,QACE,oBAAC;EAAI,WAAW,GAAG,UAAU;EAAE,GAAI;YAChC,UACC;GACE,oBAAC;IAAI,WAAW,GAAG,YAAY,MAAM;cAAG,SAAS,oBAAC,aAAW;KAAO;GACpE,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cACnC,UAAU,oBAAC,YAAS,MAAK,UAAU;KAChC;GACN,oBAAC;IAAI,WAAW,GAAG,aAAa,YAAY,KAAK;cAC/C,oBAAC,SAAS;KAAK,OAAO;KAAI,KAAK;KAAI,GAAI;MAAe;KAClD;MACL;GAED;AAIV,QACE,qBAAC;EACC,WAAW,GACT,UAED;EACD,GAAI;;GAEH,kBAAkB,QAAO,MACxB,oBAAC;IACC,OAAO;IACP,WAAW,GACT,eACA,+CAED;cAEA;KACK,CACR;GACF,oBAAC;IAAI,WAAW,GAAG,YAAY,OAAO;cAAG;KAAa;GACtD,qBAAC;IAAI,MAAK;IAAO,WAAW,GAAG,aAAa,YAAY,KAAK;;KAC1D,CAAC,MAAM,UAAU,QACd,QACA,MAAM,KAAK,MAAM,MACf,oBAAC;MAAI,MAAK;gBACP,WAAW,MAAM,EAAE;QADI,UAAU,QAAQ,MAAM,EAAE,GAAG,EAEjD,CACN;KACL,QAAQ,WACP,oBAAC;MAAI,MAAK;gBACP,QAAQ,UACP,oBAAC,SAAS;OAAK,OAAO;OAAI,KAAK;OAAI,GAAI;QAAe;OAEpD;KAEP,UAAU,oBAAC;MAAI,KAAK;MAAW,MAAK;OAAS;;KAC1C;;GACF"}
@@ -54,7 +54,7 @@ declare const Modal: {
54
54
  onCancel,
55
55
  ...props
56
56
  }: Props): react_jsx_runtime0.JSX.Element | null;
57
- destroy(id?: string): void;
57
+ destroy: (id?: string) => void;
58
58
  destroyAll(): void;
59
59
  info(props: StaticProps): string | undefined;
60
60
  success(props: StaticProps): string | undefined;
@@ -63,5 +63,5 @@ declare const Modal: {
63
63
  confirm(props: StaticProps): string | undefined;
64
64
  };
65
65
  //#endregion
66
- export { Modal };
66
+ export { Modal, Props };
67
67
  //# sourceMappingURL=modal.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.mts","names":[],"sources":["../../../src/components/organisms/modal.tsx"],"mappings":";;;;UA6BU,KAAA;EACR,IAAA;EACA,YAAA;EACA,QAAA;IAGM,SAAA,GAAY,KAAA,CAAM,SAAA;IAClB,QAAA;EAAA;EAEN,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,OAAA,GAAU,KAAA,CAAM,SAAA;EAChB,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,SAAA;EACA,UAAA;IACE,IAAA;IACA,MAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,MAAA;EACA,UAAA;EACA,SAAA,GAAY,WAAA;EACZ,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,IAAA;EACA,QAAA;AAAA;AAAA,UAGQ,WAAA,SAAoB,KAAA;EAC5B,IAAA;EACA,EAAA;EACA,IAAA,GAAO,KAAA,CAAM,SAAA;EACb,SAAA,GAAY,WAAA;AAAA;AAAA,cAmDR,KAAA;EAAA;;;;;;;;;;;;;;;;;;KAkBH,KAAA,GAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;;;cAgQa,WAAA;iBACG,WAAA;eAEF,WAAA;iBACE,WAAA;iBAEA,WAAA;AAAA"}
1
+ {"version":3,"file":"modal.d.mts","names":[],"sources":["../../../src/components/organisms/modal.tsx"],"mappings":";;;;UAgCiB,KAAA;EACf,IAAA;EACA,YAAA;EACA,QAAA;IAGM,SAAA,GAAY,KAAA,CAAM,SAAA;IAClB,QAAA;EAAA;EAEN,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,OAAA,GAAU,KAAA,CAAM,SAAA;EAChB,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,SAAA;EACA,UAAA;IACE,IAAA;IACA,MAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,MAAA;EACA,UAAA;EACA,SAAA,GAAY,WAAA;EACZ,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,IAAA;EACA,QAAA;AAAA;AAAA,UAGQ,WAAA,SAAoB,KAAA;EAC5B,IAAA;EACA,EAAA;EACA,IAAA,GAAO,KAAA,CAAM,SAAA;EACb,SAAA,GAAY,WAAA;AAAA;AAAA,cAGR,KAAA;EAAA;;;;;;;;;;;;;;;;;;KAkBH,KAAA,GAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;;;cAoMa,WAAA;iBAEG,WAAA;eAEF,WAAA;iBAEE,WAAA;iBAEA,WAAA;AAAA"}