@jongh/ui 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/index.css +1 -0
- package/.storybook/main.ts +40 -0
- package/.storybook/preview.ts +16 -0
- package/.storybook/vitest.setup.ts +9 -0
- package/.turbo/turbo-build.log +79 -0
- package/CHANGELOG.md +54 -0
- package/chromatic.config.json +6 -0
- package/eslint.config.mjs +14 -0
- package/index.html +13 -0
- package/package.json +58 -0
- package/panda.config.ts +13 -0
- package/postcss.config.cjs +3 -0
- package/preset.ts +134 -0
- package/src/component/accordion/ui/index.tsx +80 -0
- package/src/component/accordion/ui/recipe.ts +65 -0
- package/src/component/avatar/ui/index.tsx +47 -0
- package/src/component/avatar/ui/recipe.ts +30 -0
- package/src/component/button/ui/index.tsx +29 -0
- package/src/component/button/ui/recipe.ts +102 -0
- package/src/component/chip/ui/index.tsx +30 -0
- package/src/component/chip/ui/recipe.ts +112 -0
- package/src/component/dialog/ui/index.tsx +73 -0
- package/src/component/dialog/ui/recipe.ts +92 -0
- package/src/component/select/ui/index.tsx +128 -0
- package/src/component/select/ui/recipe.ts +142 -0
- package/src/component/slider/ui/index.tsx +61 -0
- package/src/component/slider/ui/recipe.ts +52 -0
- package/src/component/tabs/ui/index.tsx +61 -0
- package/src/component/tabs/ui/recipe.ts +59 -0
- package/src/hooks/createContext.tsx +34 -0
- package/src/hooks/useComposedRefs.ts +20 -0
- package/src/hooks/useControllableState.ts +87 -0
- package/src/hooks/useKeyboardEvent.ts +58 -0
- package/src/stories/accordion.stories.tsx +63 -0
- package/src/stories/avatar.stories.tsx +33 -0
- package/src/stories/button.stories.tsx +53 -0
- package/src/stories/chip.stories.tsx +69 -0
- package/src/stories/dialog.stories.tsx +134 -0
- package/src/stories/select.stories.tsx +35 -0
- package/src/stories/slider.stories.tsx +31 -0
- package/src/stories/tabs.stories.tsx +63 -0
- package/src/test/accordion.test.tsx +66 -0
- package/src/test/tabs.test.tsx +30 -0
- package/src/types/index.ts +1 -0
- package/src/utils/createStyleContext.tsx +108 -0
- package/src/utils/defineSafe.ts +46 -0
- package/src/utils/getObjectKeys.ts +20 -0
- package/src/vite-env.d.ts +1 -0
- package/storybook-static/assets/Color-F6OSRLHC-CrKta8Qx.js +1 -0
- package/storybook-static/assets/DocsRenderer-CFRXHY34-Crd9Mepd.js +586 -0
- package/storybook-static/assets/_commonjsHelpers-Cpj98o6Y.js +1 -0
- package/storybook-static/assets/accordion.stories-0Om0AnMm.js +50 -0
- package/storybook-static/assets/avatar.stories-DMDsrSks.js +16 -0
- package/storybook-static/assets/axe-Dzet_oDA.js +30 -0
- package/storybook-static/assets/button.stories-CuVC-3x-.js +40 -0
- package/storybook-static/assets/chip.stories-FBIp8XNi.js +48 -0
- package/storybook-static/assets/chunk-XP5HYGXS-D5tuasO7.js +1 -0
- package/storybook-static/assets/createLucideIcon-DmXe7Z8R.js +21 -0
- package/storybook-static/assets/dialog.stories-3WsEvXt4.js +106 -0
- package/storybook-static/assets/entry-preview-Bkgdgq1b.js +10 -0
- package/storybook-static/assets/entry-preview-docs-zLz1Es7d.js +46 -0
- package/storybook-static/assets/iframe-LPPPXabV.js +199 -0
- package/storybook-static/assets/index-Bklpsb39.js +1 -0
- package/storybook-static/assets/index-BrlJLjep.js +24 -0
- package/storybook-static/assets/index-C2tRLqin.js +41 -0
- package/storybook-static/assets/index-CBft-ReK.js +8 -0
- package/storybook-static/assets/index-CSbWd7UJ.js +1 -0
- package/storybook-static/assets/index-ClcD9ViR.js +9 -0
- package/storybook-static/assets/index-Cu4lwwaE.js +1 -0
- package/storybook-static/assets/index-Cvkemp2J.js +1 -0
- package/storybook-static/assets/index-D59aU5s_.js +240 -0
- package/storybook-static/assets/index-DNo8LKN3.js +1 -0
- package/storybook-static/assets/index-DUy19JZU.js +1 -0
- package/storybook-static/assets/index-D_35mznO.js +1 -0
- package/storybook-static/assets/index-DrFu-skq.js +6 -0
- package/storybook-static/assets/index-DvbTp2M2.js +1 -0
- package/storybook-static/assets/index-rtmQni2k.js +1 -0
- package/storybook-static/assets/jsx-runtime-BYYWji4R.js +9 -0
- package/storybook-static/assets/matchers-57EZJSQE-oeXCqs4p.js +14 -0
- package/storybook-static/assets/preview-1l6V4UsQ.js +1 -0
- package/storybook-static/assets/preview-B3PTUHS7.js +1 -0
- package/storybook-static/assets/preview-BBWR9nbA.js +1 -0
- package/storybook-static/assets/preview-BCV5r-Ja.js +1 -0
- package/storybook-static/assets/preview-BWzBA1C2.js +396 -0
- package/storybook-static/assets/preview-Bb56VplF.js +2 -0
- package/storybook-static/assets/preview-Bl8rsKRy.js +1 -0
- package/storybook-static/assets/preview-Bm-a94Ct.js +2 -0
- package/storybook-static/assets/preview-Br-h4d84.js +1 -0
- package/storybook-static/assets/preview-D77C14du.js +34 -0
- package/storybook-static/assets/preview-DC8N7cZb.css +1 -0
- package/storybook-static/assets/preview-DGUiP6tS.js +7 -0
- package/storybook-static/assets/react-18-BPs3tMGP.js +1 -0
- package/storybook-static/assets/select.stories-AN8Hb81Z.js +20 -0
- package/storybook-static/assets/slider.stories-CxOczq0y.js +12 -0
- package/storybook-static/assets/tabs.stories-BbTU4QU3.js +28 -0
- package/storybook-static/favicon.svg +1 -0
- package/storybook-static/iframe.html +666 -0
- package/storybook-static/index.html +193 -0
- package/storybook-static/index.json +1 -0
- package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/project.json +1 -0
- package/storybook-static/sb-addons/a11y-12/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/a11y-12/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
- package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
- package/storybook-static/sb-addons/controls-11/manager-bundle.js +391 -0
- package/storybook-static/sb-addons/controls-11/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
- package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js +391 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js +230 -0
- package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js +211 -0
- package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-common-assets/favicon.svg +1 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/globals-module-info.js +1037 -0
- package/storybook-static/sb-manager/globals-runtime.js +40857 -0
- package/storybook-static/sb-manager/globals.js +48 -0
- package/storybook-static/sb-manager/runtime.js +11963 -0
- package/styled-system/css/conditions.mjs +36 -0
- package/styled-system/css/css.d.ts +22 -0
- package/styled-system/css/css.mjs +45 -0
- package/styled-system/css/cva.d.ts +6 -0
- package/styled-system/css/cva.mjs +87 -0
- package/styled-system/css/cx.d.ts +5 -0
- package/styled-system/css/cx.mjs +15 -0
- package/styled-system/css/index.d.ts +5 -0
- package/styled-system/css/index.mjs +4 -0
- package/styled-system/css/sva.d.ts +4 -0
- package/styled-system/css/sva.mjs +41 -0
- package/styled-system/helpers.mjs +336 -0
- package/styled-system/jsx/aspect-ratio.d.ts +10 -0
- package/styled-system/jsx/aspect-ratio.mjs +14 -0
- package/styled-system/jsx/bleed.d.ts +10 -0
- package/styled-system/jsx/bleed.mjs +14 -0
- package/styled-system/jsx/box.d.ts +10 -0
- package/styled-system/jsx/box.mjs +14 -0
- package/styled-system/jsx/center.d.ts +10 -0
- package/styled-system/jsx/center.mjs +14 -0
- package/styled-system/jsx/circle.d.ts +10 -0
- package/styled-system/jsx/circle.mjs +14 -0
- package/styled-system/jsx/container.d.ts +10 -0
- package/styled-system/jsx/container.mjs +14 -0
- package/styled-system/jsx/cq.d.ts +10 -0
- package/styled-system/jsx/cq.mjs +14 -0
- package/styled-system/jsx/divider.d.ts +10 -0
- package/styled-system/jsx/divider.mjs +14 -0
- package/styled-system/jsx/factory-helper.mjs +22 -0
- package/styled-system/jsx/factory.d.ts +3 -0
- package/styled-system/jsx/factory.mjs +80 -0
- package/styled-system/jsx/flex.d.ts +10 -0
- package/styled-system/jsx/flex.mjs +14 -0
- package/styled-system/jsx/float.d.ts +10 -0
- package/styled-system/jsx/float.mjs +14 -0
- package/styled-system/jsx/grid-item.d.ts +10 -0
- package/styled-system/jsx/grid-item.mjs +14 -0
- package/styled-system/jsx/grid.d.ts +10 -0
- package/styled-system/jsx/grid.mjs +14 -0
- package/styled-system/jsx/hstack.d.ts +10 -0
- package/styled-system/jsx/hstack.mjs +14 -0
- package/styled-system/jsx/index.d.ts +24 -0
- package/styled-system/jsx/index.mjs +22 -0
- package/styled-system/jsx/is-valid-prop.d.ts +11 -0
- package/styled-system/jsx/is-valid-prop.mjs +17 -0
- package/styled-system/jsx/link-overlay.d.ts +10 -0
- package/styled-system/jsx/link-overlay.mjs +14 -0
- package/styled-system/jsx/spacer.d.ts +10 -0
- package/styled-system/jsx/spacer.mjs +14 -0
- package/styled-system/jsx/square.d.ts +10 -0
- package/styled-system/jsx/square.mjs +14 -0
- package/styled-system/jsx/stack.d.ts +10 -0
- package/styled-system/jsx/stack.mjs +14 -0
- package/styled-system/jsx/visually-hidden.d.ts +10 -0
- package/styled-system/jsx/visually-hidden.mjs +14 -0
- package/styled-system/jsx/vstack.d.ts +10 -0
- package/styled-system/jsx/vstack.mjs +14 -0
- package/styled-system/jsx/wrap.d.ts +10 -0
- package/styled-system/jsx/wrap.mjs +14 -0
- package/styled-system/patterns/aspect-ratio.d.ts +21 -0
- package/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/styled-system/patterns/bleed.d.ts +22 -0
- package/styled-system/patterns/bleed.mjs +24 -0
- package/styled-system/patterns/box.d.ts +21 -0
- package/styled-system/patterns/box.mjs +15 -0
- package/styled-system/patterns/center.d.ts +21 -0
- package/styled-system/patterns/center.mjs +21 -0
- package/styled-system/patterns/circle.d.ts +21 -0
- package/styled-system/patterns/circle.mjs +25 -0
- package/styled-system/patterns/container.d.ts +21 -0
- package/styled-system/patterns/container.mjs +21 -0
- package/styled-system/patterns/cq.d.ts +22 -0
- package/styled-system/patterns/cq.mjs +21 -0
- package/styled-system/patterns/divider.d.ts +23 -0
- package/styled-system/patterns/divider.mjs +25 -0
- package/styled-system/patterns/flex.d.ts +27 -0
- package/styled-system/patterns/flex.mjs +26 -0
- package/styled-system/patterns/float.d.ts +24 -0
- package/styled-system/patterns/float.mjs +52 -0
- package/styled-system/patterns/grid-item.d.ts +26 -0
- package/styled-system/patterns/grid-item.mjs +25 -0
- package/styled-system/patterns/grid.d.ts +25 -0
- package/styled-system/patterns/grid.mjs +27 -0
- package/styled-system/patterns/hstack.d.ts +22 -0
- package/styled-system/patterns/hstack.mjs +24 -0
- package/styled-system/patterns/index.d.ts +21 -0
- package/styled-system/patterns/index.mjs +20 -0
- package/styled-system/patterns/link-overlay.d.ts +21 -0
- package/styled-system/patterns/link-overlay.mjs +24 -0
- package/styled-system/patterns/spacer.d.ts +21 -0
- package/styled-system/patterns/spacer.mjs +21 -0
- package/styled-system/patterns/square.d.ts +21 -0
- package/styled-system/patterns/square.mjs +24 -0
- package/styled-system/patterns/stack.d.ts +24 -0
- package/styled-system/patterns/stack.mjs +24 -0
- package/styled-system/patterns/visually-hidden.d.ts +21 -0
- package/styled-system/patterns/visually-hidden.mjs +18 -0
- package/styled-system/patterns/vstack.d.ts +22 -0
- package/styled-system/patterns/vstack.mjs +24 -0
- package/styled-system/patterns/wrap.d.ts +25 -0
- package/styled-system/patterns/wrap.mjs +25 -0
- package/styled-system/tokens/index.d.ts +9 -0
- package/styled-system/tokens/index.mjs +1992 -0
- package/styled-system/tokens/tokens.d.ts +60 -0
- package/styled-system/types/composition.d.ts +164 -0
- package/styled-system/types/conditions.d.ts +274 -0
- package/styled-system/types/csstype.d.ts +21298 -0
- package/styled-system/types/global.d.ts +20 -0
- package/styled-system/types/index.d.ts +8 -0
- package/styled-system/types/jsx.d.ts +52 -0
- package/styled-system/types/parts.d.ts +8 -0
- package/styled-system/types/pattern.d.ts +78 -0
- package/styled-system/types/prop-type.d.ts +235 -0
- package/styled-system/types/recipe.d.ts +181 -0
- package/styled-system/types/selectors.d.ts +59 -0
- package/styled-system/types/static-css.d.ts +56 -0
- package/styled-system/types/style-props.d.ts +7468 -0
- package/styled-system/types/system-types.d.ts +109 -0
- package/tsconfig.json +13 -0
- package/turbo/generators/config.cjs +7 -0
- package/turbo/generators/stories.cjs +23 -0
- package/turbo/generators/templates/stories.tsx.hbs +16 -0
- package/turbo/generators/templates/ui.tsx.hbs +8 -0
- package/turbo/generators/ui.cjs +19 -0
- package/vite.config.ts +7 -0
- package/vitest.config.ts +45 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { expect, fn, userEvent, within } from "@storybook/test"
|
|
3
|
+
import type { ComponentProps } from "react"
|
|
4
|
+
|
|
5
|
+
import { Button } from "../component/button/ui"
|
|
6
|
+
export default {
|
|
7
|
+
title: "Button",
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
component: Button,
|
|
10
|
+
} as Meta<typeof Button>
|
|
11
|
+
|
|
12
|
+
type Story = StoryObj<ComponentProps<typeof Button>>
|
|
13
|
+
|
|
14
|
+
export const Primary: Story = {
|
|
15
|
+
args: {
|
|
16
|
+
children: "click",
|
|
17
|
+
onClick: fn(),
|
|
18
|
+
},
|
|
19
|
+
play: async ({ args, canvasElement }) => {
|
|
20
|
+
const canvas = within(canvasElement)
|
|
21
|
+
const button = canvas.getByRole("button")
|
|
22
|
+
await userEvent.click(button)
|
|
23
|
+
await expect(args.onClick).toHaveBeenCalled()
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const Secondary: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
children: "click",
|
|
30
|
+
variant: "secondary",
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const Ghost: Story = {
|
|
35
|
+
args: {
|
|
36
|
+
children: "click",
|
|
37
|
+
variant: "outline",
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const Disabled: Story = {
|
|
42
|
+
args: {
|
|
43
|
+
disabled: true,
|
|
44
|
+
children: "disabled",
|
|
45
|
+
onClick: fn(),
|
|
46
|
+
},
|
|
47
|
+
play: async ({ args, canvasElement }) => {
|
|
48
|
+
const canvas = within(canvasElement)
|
|
49
|
+
const button = canvas.getByRole("button")
|
|
50
|
+
await userEvent.click(button)
|
|
51
|
+
await expect(args.onClick).not.toHaveBeenCalled()
|
|
52
|
+
},
|
|
53
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { expect, fn, userEvent } from "@storybook/test"
|
|
3
|
+
import { PlusCircleIcon } from "lucide-react"
|
|
4
|
+
import { ComponentProps } from "react"
|
|
5
|
+
|
|
6
|
+
import { Chip } from "../component/chip/ui"
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: "Chip",
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
component: Chip,
|
|
12
|
+
} as Meta<typeof Chip>
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj<ComponentProps<typeof Chip>>
|
|
15
|
+
|
|
16
|
+
export const Primary: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
children: <div>확인</div>,
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const Outlined: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
children: <div>확인</div>,
|
|
25
|
+
variant: "outlined",
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const IconOnly: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
layout: "iconOnly",
|
|
32
|
+
children: <PlusCircleIcon />,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const WithPrefixIcon: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
children: (
|
|
39
|
+
<>
|
|
40
|
+
<PlusCircleIcon />
|
|
41
|
+
ㅎㅇ
|
|
42
|
+
</>
|
|
43
|
+
),
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const WithSuffixIcon: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
children: (
|
|
50
|
+
<>
|
|
51
|
+
ㅎㅇ
|
|
52
|
+
<PlusCircleIcon />
|
|
53
|
+
</>
|
|
54
|
+
),
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const Disabled: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
disabled: true,
|
|
61
|
+
children: "disabled",
|
|
62
|
+
onClick: fn(),
|
|
63
|
+
},
|
|
64
|
+
play: async ({ args, canvas }) => {
|
|
65
|
+
const button = canvas.getByRole("button")
|
|
66
|
+
await userEvent.click(button)
|
|
67
|
+
await expect(args.onClick).not.toHaveBeenCalled()
|
|
68
|
+
},
|
|
69
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import {
|
|
3
|
+
expect,
|
|
4
|
+
screen,
|
|
5
|
+
userEvent,
|
|
6
|
+
waitForElementToBeRemoved,
|
|
7
|
+
within,
|
|
8
|
+
} from "@storybook/test"
|
|
9
|
+
import { css } from "@styled-system/css"
|
|
10
|
+
|
|
11
|
+
import * as Dialog from "../component/dialog/ui"
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Dialog",
|
|
15
|
+
tags: ["autodocs"],
|
|
16
|
+
} satisfies Meta<typeof Dialog>
|
|
17
|
+
|
|
18
|
+
export default meta
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<typeof meta>
|
|
21
|
+
|
|
22
|
+
export const Primary: Story = {
|
|
23
|
+
render: () => {
|
|
24
|
+
return (
|
|
25
|
+
<Dialog.Root>
|
|
26
|
+
<Dialog.Trigger>Open</Dialog.Trigger>
|
|
27
|
+
<Dialog.Content>
|
|
28
|
+
<Dialog.Header>
|
|
29
|
+
<Dialog.Title>Dialog</Dialog.Title>
|
|
30
|
+
<Dialog.Description>
|
|
31
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
|
|
32
|
+
venenatis feugiat eros aliquam convallis. Donec tincidunt eros sed
|
|
33
|
+
ligula tincidunt, sit amet tristique purus pulvinar. Donec maximus
|
|
34
|
+
nunc vitae vestibulum cursus. Phasellus laoreet, velit non mollis
|
|
35
|
+
semper, nunc dui accumsan orci, consequat accumsan libero quam ac
|
|
36
|
+
est. Pellentesque habitant morbi tristique senectus et netus et
|
|
37
|
+
malesuada fames ac turpis egestas. Phasellus ac turpis neque.
|
|
38
|
+
Class aptent taciti sociosqu ad litora torquent per conubia
|
|
39
|
+
nostra, per inceptos himenaeos.
|
|
40
|
+
</Dialog.Description>
|
|
41
|
+
</Dialog.Header>
|
|
42
|
+
</Dialog.Content>
|
|
43
|
+
</Dialog.Root>
|
|
44
|
+
)
|
|
45
|
+
},
|
|
46
|
+
play: async ({ canvasElement }) => {
|
|
47
|
+
//canvasElement -> storybook의 #storybook-root
|
|
48
|
+
//React portal API를 사용할 경우 다른곳에 렌더링
|
|
49
|
+
//더 넓은 범위의 screen으로 테스트하는게 더 올바른 방법이라고 생각
|
|
50
|
+
const canvas = within(canvasElement)
|
|
51
|
+
const ButtonElement = canvas.getByRole("button")
|
|
52
|
+
await userEvent.click(ButtonElement)
|
|
53
|
+
const CloseElement = screen.getByText("Close")
|
|
54
|
+
expect(CloseElement).not.toBeNull()
|
|
55
|
+
|
|
56
|
+
await userEvent.click(CloseElement)
|
|
57
|
+
|
|
58
|
+
waitForElementToBeRemoved(CloseElement).then(() =>
|
|
59
|
+
expect(CloseElement).not.toBeInTheDocument(),
|
|
60
|
+
)
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const LongText: Story = {
|
|
65
|
+
render: () => {
|
|
66
|
+
return (
|
|
67
|
+
<Dialog.Root>
|
|
68
|
+
<Dialog.Trigger
|
|
69
|
+
className={css({
|
|
70
|
+
textStyle: "6xl",
|
|
71
|
+
})}
|
|
72
|
+
>
|
|
73
|
+
Open
|
|
74
|
+
</Dialog.Trigger>
|
|
75
|
+
<Dialog.Content
|
|
76
|
+
className={css({
|
|
77
|
+
bg: "cyan.600",
|
|
78
|
+
})}
|
|
79
|
+
>
|
|
80
|
+
<Dialog.Header>
|
|
81
|
+
<Dialog.Title
|
|
82
|
+
className={css({
|
|
83
|
+
color: "red.100",
|
|
84
|
+
})}
|
|
85
|
+
>
|
|
86
|
+
Dialog
|
|
87
|
+
</Dialog.Title>
|
|
88
|
+
<Dialog.Description
|
|
89
|
+
className={css({
|
|
90
|
+
fontSize: "sm",
|
|
91
|
+
})}
|
|
92
|
+
>
|
|
93
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
|
|
94
|
+
venenatis feugiat eros aliquam convallis. Donec tincidunt eros sed
|
|
95
|
+
ligula tincidunt, sit amet tristique purus pulvinar. Donec maximus
|
|
96
|
+
nunc vitae vestibulum cursus. Phasellus laoreet, velit non mollis
|
|
97
|
+
semper, nunc dui accumsan orci, consequat accumsan libero quam ac
|
|
98
|
+
est. Pellentesque habitant morbi tristique senectus et netus et
|
|
99
|
+
malesuada fames ac turpis egestas. Phasellus ac turpis neque.
|
|
100
|
+
Class aptent taciti sociosqu ad litora torquent per conubia
|
|
101
|
+
nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet,
|
|
102
|
+
consectetur adipiscing elit. Integer venenatis feugiat eros
|
|
103
|
+
aliquam convallis. Donec tincidunt eros sed ligula tincidunt, sit
|
|
104
|
+
amet tristique purus pulvinar. Donec maximus nunc vitae vestibulum
|
|
105
|
+
cursus. Phasellus laoreet, velit non mollis semper, nunc dui
|
|
106
|
+
accumsan orci, consequat accumsan libero quam ac est. Pellentesque
|
|
107
|
+
habitant morbi tristique senectus et netus et malesuada fames ac
|
|
108
|
+
turpis egestas. Phasellus ac turpis neque. Class aptent taciti
|
|
109
|
+
sociosqu ad litora torquent per conubia nostra, per inceptos
|
|
110
|
+
himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing
|
|
111
|
+
elit. Integer venenatis feugiat eros aliquam convallis. Donec
|
|
112
|
+
tincidunt eros sed ligula tincidunt, sit amet tristique purus
|
|
113
|
+
pulvinar. Donec maximus nunc vitae vestibulum cursus. Phasellus
|
|
114
|
+
laoreet, velit non mollis semper, nunc dui accumsan orci,
|
|
115
|
+
consequat accumsan libero quam ac est. Pellentesque habitant morbi
|
|
116
|
+
tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
117
|
+
Phasellus ac turpis neque. Class aptent taciti sociosqu ad litora
|
|
118
|
+
torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum
|
|
119
|
+
dolor sit amet, consectetur adipiscing elit. Integer venenatis
|
|
120
|
+
feugiat eros aliquam convallis. Donec tincidunt eros sed ligula
|
|
121
|
+
tincidunt, sit amet tristique purus pulvinar. Donec maximus nunc
|
|
122
|
+
vitae vestibulum cursus. Phasellus laoreet, velit non mollis
|
|
123
|
+
semper, nunc dui accumsan orci, consequat accumsan libero quam ac
|
|
124
|
+
est. Pellentesque habitant morbi tristique senectus et netus et
|
|
125
|
+
malesuada fames ac turpis egestas. Phasellus ac turpis neque.
|
|
126
|
+
Class aptent taciti sociosqu ad litora torquent per conubia
|
|
127
|
+
nostra, per inceptos himenaeos.
|
|
128
|
+
</Dialog.Description>
|
|
129
|
+
</Dialog.Header>
|
|
130
|
+
</Dialog.Content>
|
|
131
|
+
</Dialog.Root>
|
|
132
|
+
)
|
|
133
|
+
},
|
|
134
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
|
|
3
|
+
import * as Select from "../component/select/ui"
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: "Select",
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
} satisfies Meta<typeof Select>
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj<typeof Select>
|
|
11
|
+
|
|
12
|
+
const arr = Array.from({ length: 100 }, (_, i) => i)
|
|
13
|
+
//부모 요소의 width 고정값 or Trigger의 width 고정값 필요
|
|
14
|
+
export const Primary: Story = {
|
|
15
|
+
render: () => {
|
|
16
|
+
return (
|
|
17
|
+
<div style={{ width: "300px" }}>
|
|
18
|
+
<Select.Root>
|
|
19
|
+
<Select.Trigger>
|
|
20
|
+
<Select.Value placeholder="Select a frui" />
|
|
21
|
+
</Select.Trigger>
|
|
22
|
+
<Select.Content>
|
|
23
|
+
<Select.Group>
|
|
24
|
+
{arr.map((num) => (
|
|
25
|
+
<Select.Item key={num} value={num.toString()}>
|
|
26
|
+
{num}
|
|
27
|
+
</Select.Item>
|
|
28
|
+
))}
|
|
29
|
+
</Select.Group>
|
|
30
|
+
</Select.Content>
|
|
31
|
+
</Select.Root>
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
34
|
+
},
|
|
35
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { css } from "@styled-system/css"
|
|
3
|
+
|
|
4
|
+
import * as Slider from "../component/slider/ui"
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: "Slider",
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
} satisfies Meta<typeof Slider>
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof Slider>
|
|
12
|
+
|
|
13
|
+
export const Primary: Story = {
|
|
14
|
+
render: () => {
|
|
15
|
+
return (
|
|
16
|
+
<Slider.Root
|
|
17
|
+
defaultValue={[50, 100]}
|
|
18
|
+
max={100}
|
|
19
|
+
step={2}
|
|
20
|
+
className={css({
|
|
21
|
+
width: "[100px]",
|
|
22
|
+
})}
|
|
23
|
+
>
|
|
24
|
+
<Slider.Track>
|
|
25
|
+
<Slider.Range />
|
|
26
|
+
</Slider.Track>
|
|
27
|
+
<Slider.Thumb />
|
|
28
|
+
</Slider.Root>
|
|
29
|
+
)
|
|
30
|
+
},
|
|
31
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import { useState } from "@storybook/preview-api"
|
|
3
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
4
|
+
|
|
5
|
+
import * as Tabs from "../component/tabs/ui"
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Tabs",
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
} satisfies Meta<typeof Tabs>
|
|
11
|
+
|
|
12
|
+
export default meta
|
|
13
|
+
type Story = StoryObj<typeof meta>
|
|
14
|
+
|
|
15
|
+
const data = [
|
|
16
|
+
{ value: "1", label: "Tab 1", content: "1번" },
|
|
17
|
+
{ value: "2", label: "Tab 2", content: "2번" },
|
|
18
|
+
{ value: "3", label: "Tab 3", content: "3번" },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
export const Primary: Story = {
|
|
22
|
+
render: (args) => {
|
|
23
|
+
return (
|
|
24
|
+
<Tabs.Root {...args}>
|
|
25
|
+
<Tabs.List>
|
|
26
|
+
{data.map((item) => (
|
|
27
|
+
<Tabs.Trigger key={item.value} value={item.value}>
|
|
28
|
+
{item.label}
|
|
29
|
+
</Tabs.Trigger>
|
|
30
|
+
))}
|
|
31
|
+
</Tabs.List>
|
|
32
|
+
{data.map((item) => (
|
|
33
|
+
<Tabs.Content key={item.value} value={item.value}>
|
|
34
|
+
{item.content}
|
|
35
|
+
</Tabs.Content>
|
|
36
|
+
))}
|
|
37
|
+
</Tabs.Root>
|
|
38
|
+
)
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 제어 컴포넌트 예시
|
|
43
|
+
export const Controlled: Story = {
|
|
44
|
+
render: (args) => {
|
|
45
|
+
const [value, setValue] = useState("2")
|
|
46
|
+
return (
|
|
47
|
+
<Tabs.Root value={value} onValueChange={setValue} {...args}>
|
|
48
|
+
<Tabs.List>
|
|
49
|
+
{data.map((item) => (
|
|
50
|
+
<Tabs.Trigger key={item.value} value={item.value}>
|
|
51
|
+
{item.label}
|
|
52
|
+
</Tabs.Trigger>
|
|
53
|
+
))}
|
|
54
|
+
</Tabs.List>
|
|
55
|
+
{data.map((item) => (
|
|
56
|
+
<Tabs.Content key={item.value} value={item.value}>
|
|
57
|
+
{item.content}
|
|
58
|
+
</Tabs.Content>
|
|
59
|
+
))}
|
|
60
|
+
</Tabs.Root>
|
|
61
|
+
)
|
|
62
|
+
},
|
|
63
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react"
|
|
2
|
+
import { useState } from "react"
|
|
3
|
+
import { describe, expect, it, vi } from "vitest"
|
|
4
|
+
|
|
5
|
+
import * as Accordion from "../component/accordion/ui"
|
|
6
|
+
|
|
7
|
+
// 예시 컴포넌트
|
|
8
|
+
const AccordionExample = () => {
|
|
9
|
+
const [selectedItems, setSelectedItems] = useState<string[]>([])
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Accordion.Root
|
|
13
|
+
type="multiple"
|
|
14
|
+
value={selectedItems}
|
|
15
|
+
onValueChange={(items) => setSelectedItems(items)}
|
|
16
|
+
>
|
|
17
|
+
<Accordion.Item value="1">
|
|
18
|
+
<Accordion.Header>
|
|
19
|
+
<Accordion.Trigger data-testid="1">1번</Accordion.Trigger>
|
|
20
|
+
</Accordion.Header>
|
|
21
|
+
<Accordion.Content>내용1</Accordion.Content>
|
|
22
|
+
</Accordion.Item>
|
|
23
|
+
</Accordion.Root>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 테스트
|
|
28
|
+
describe("Accordion with useState", () => {
|
|
29
|
+
it("상태 변경 테스트", async () => {
|
|
30
|
+
render(<AccordionExample />)
|
|
31
|
+
|
|
32
|
+
// 초기 상태 확인
|
|
33
|
+
expect(screen.queryByText("내용1")).toBeDefined()
|
|
34
|
+
|
|
35
|
+
// 트리거 클릭
|
|
36
|
+
const trigger = screen.getByTestId("1")
|
|
37
|
+
await fireEvent.click(trigger)
|
|
38
|
+
|
|
39
|
+
// 상태 변경 후 내용 표시 확인
|
|
40
|
+
expect(screen.getByText("내용1")).toBeDefined()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// 외부에서 상태를 제어하는 경우 테스트
|
|
44
|
+
it("외부 상태 제어 테스트", () => {
|
|
45
|
+
const onValueChange = vi.fn()
|
|
46
|
+
|
|
47
|
+
render(
|
|
48
|
+
<Accordion.Root
|
|
49
|
+
type="multiple"
|
|
50
|
+
value={["1"]}
|
|
51
|
+
onValueChange={onValueChange}
|
|
52
|
+
>
|
|
53
|
+
<Accordion.Item value="1">
|
|
54
|
+
<Accordion.Trigger data-testid="trigger-1">1번</Accordion.Trigger>
|
|
55
|
+
<Accordion.Content>내용1</Accordion.Content>
|
|
56
|
+
</Accordion.Item>
|
|
57
|
+
</Accordion.Root>,
|
|
58
|
+
)
|
|
59
|
+
//Fix: getByText로 찾을 시 multiple error 발생
|
|
60
|
+
const trigger = screen.getByTestId("trigger-1")
|
|
61
|
+
|
|
62
|
+
fireEvent.click(trigger)
|
|
63
|
+
|
|
64
|
+
expect(onValueChange).toHaveBeenCalledWith([])
|
|
65
|
+
})
|
|
66
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { composeStories } from "@storybook/react"
|
|
2
|
+
import { screen } from "@testing-library/react"
|
|
3
|
+
import userEvent from "@testing-library/user-event"
|
|
4
|
+
import { expect, test } from "vitest"
|
|
5
|
+
|
|
6
|
+
import * as stories from "../stories/tabs.stories"
|
|
7
|
+
|
|
8
|
+
const { Primary } = composeStories(stories)
|
|
9
|
+
|
|
10
|
+
test("초기 렌더링 시 defaultValue가 존재하면 해당되는 탭이 선택됩니다", async () => {
|
|
11
|
+
await Primary.run({ args: { ...Primary.args } })
|
|
12
|
+
expect(screen.getByText("Tab 1")).toBeDefined()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test("클릭 시 해당 tab에 대한 content가 노출됩니다", async () => {
|
|
16
|
+
const user = userEvent.setup()
|
|
17
|
+
await Primary.run({ args: { ...Primary.args } })
|
|
18
|
+
await user.click(screen.getByText("Tab 2"))
|
|
19
|
+
expect(screen.getByText("2번")).toBeDefined()
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test("arrow key를 통해 탭을 조작할 수 있습니다", async () => {
|
|
23
|
+
const user = userEvent.setup()
|
|
24
|
+
await Primary.run()
|
|
25
|
+
|
|
26
|
+
await user.click(screen.getByText("Tab 2"))
|
|
27
|
+
await user.keyboard("{ArrowLeft}")
|
|
28
|
+
|
|
29
|
+
expect(document.activeElement).toBe(screen.getByText("Tab 1"))
|
|
30
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Assign<T, U> = Omit<T, keyof U> & U
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
type ElementType,
|
|
4
|
+
forwardRef,
|
|
5
|
+
type ForwardRefExoticComponent,
|
|
6
|
+
type PropsWithoutRef,
|
|
7
|
+
type RefAttributes,
|
|
8
|
+
useContext,
|
|
9
|
+
} from "react"
|
|
10
|
+
import { cx } from "styled-system/css"
|
|
11
|
+
import { isCssProperty, styled, type StyledComponent } from "styled-system/jsx"
|
|
12
|
+
|
|
13
|
+
type Props = Record<string, unknown>
|
|
14
|
+
type Recipe = {
|
|
15
|
+
(props?: Props): Props
|
|
16
|
+
splitVariantProps: (props: Props) => [Props, Props]
|
|
17
|
+
}
|
|
18
|
+
type Slot<R extends Recipe> = keyof ReturnType<R>
|
|
19
|
+
type Options = { forwardProps?: string[] }
|
|
20
|
+
|
|
21
|
+
const shouldForwardProp = (
|
|
22
|
+
prop: string,
|
|
23
|
+
variantKeys: string[],
|
|
24
|
+
options: Options = {},
|
|
25
|
+
) =>
|
|
26
|
+
options.forwardProps?.includes(prop) ||
|
|
27
|
+
(!variantKeys.includes(prop) && !isCssProperty(prop))
|
|
28
|
+
|
|
29
|
+
export const createStyleContext = <R extends Recipe>(recipe: R) => {
|
|
30
|
+
const StyleContext = createContext<Record<Slot<R>, string> | null>(null)
|
|
31
|
+
|
|
32
|
+
const withRootProvider = (Component: ElementType) => {
|
|
33
|
+
const StyledComponent = (props: Props) => {
|
|
34
|
+
const [variantProps, otherProps] = recipe.splitVariantProps(props)
|
|
35
|
+
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<StyleContext.Provider value={slotStyles}>
|
|
39
|
+
<Component {...otherProps} />
|
|
40
|
+
</StyleContext.Provider>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
return StyledComponent
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const withProvider = <T, P extends { className?: string | undefined }>(
|
|
47
|
+
Component: ElementType,
|
|
48
|
+
slot: Slot<R>,
|
|
49
|
+
options?: Options,
|
|
50
|
+
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
|
|
51
|
+
const StyledComponent = styled(
|
|
52
|
+
Component,
|
|
53
|
+
{},
|
|
54
|
+
{
|
|
55
|
+
shouldForwardProp: (prop, variantKeys) =>
|
|
56
|
+
shouldForwardProp(prop, variantKeys, options),
|
|
57
|
+
},
|
|
58
|
+
) as StyledComponent<ElementType>
|
|
59
|
+
const StyledSlotProvider = forwardRef<T, P>((props, ref) => {
|
|
60
|
+
const [variantProps, otherProps] = recipe.splitVariantProps(props)
|
|
61
|
+
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<StyleContext.Provider value={slotStyles}>
|
|
65
|
+
<StyledComponent
|
|
66
|
+
{...otherProps}
|
|
67
|
+
ref={ref}
|
|
68
|
+
className={cx(slotStyles?.[slot], props.className)}
|
|
69
|
+
/>
|
|
70
|
+
</StyleContext.Provider>
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
// @ts-expect-error '''
|
|
74
|
+
StyledSlotProvider.displayName = Component.displayName || Component.name
|
|
75
|
+
|
|
76
|
+
return StyledSlotProvider
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const withContext = <T, P extends { className?: string | undefined }>(
|
|
80
|
+
Component: ElementType,
|
|
81
|
+
slot: Slot<R>,
|
|
82
|
+
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
|
|
83
|
+
const StyledComponent = styled(Component)
|
|
84
|
+
const StyledSlotComponent = forwardRef<T, P>((props, ref) => {
|
|
85
|
+
const slotStyles = useContext(StyleContext)
|
|
86
|
+
return (
|
|
87
|
+
<StyledComponent
|
|
88
|
+
{...props}
|
|
89
|
+
ref={ref}
|
|
90
|
+
className={cx(slotStyles?.[slot], props.className)}
|
|
91
|
+
/>
|
|
92
|
+
)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
StyledSlotComponent.displayName =
|
|
96
|
+
typeof Component === "function"
|
|
97
|
+
? Component.displayName || Component.name
|
|
98
|
+
: String(Component)
|
|
99
|
+
|
|
100
|
+
return StyledSlotComponent
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
withRootProvider,
|
|
105
|
+
withProvider,
|
|
106
|
+
withContext,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RecipeConfig,
|
|
3
|
+
SlotRecipeConfig,
|
|
4
|
+
SystemStyleObject,
|
|
5
|
+
TextStyles,
|
|
6
|
+
} from "@pandacss/dev"
|
|
7
|
+
import {
|
|
8
|
+
RecipeConfig as CodegenRecipeConfig,
|
|
9
|
+
RecipeVariantRecord,
|
|
10
|
+
SlotRecipeConfig as CodegenSlotRecipeConfig,
|
|
11
|
+
SlotRecipeVariantRecord,
|
|
12
|
+
SystemStyleObject as CodegenSystemStyleObject,
|
|
13
|
+
} from "@styled-system/types"
|
|
14
|
+
import { TextStyle } from "@styled-system/types/composition"
|
|
15
|
+
|
|
16
|
+
function defineSafeRecipe<T extends RecipeVariantRecord>(
|
|
17
|
+
config: CodegenRecipeConfig<T>,
|
|
18
|
+
): RecipeConfig {
|
|
19
|
+
return config as RecipeConfig
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function defineSafeSlotRecipe<
|
|
23
|
+
S extends string,
|
|
24
|
+
T extends SlotRecipeVariantRecord<S>,
|
|
25
|
+
>(config: CodegenSlotRecipeConfig<S, T>): SlotRecipeConfig {
|
|
26
|
+
return config as SlotRecipeConfig
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface Token<T> {
|
|
30
|
+
value: T
|
|
31
|
+
description?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Recursive<T> {
|
|
35
|
+
// @ts-expect-error this makes the textStyles typings happy
|
|
36
|
+
value?: T
|
|
37
|
+
[key: string]: Recursive<T> | T
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const defineSafe = {
|
|
41
|
+
recipe: defineSafeRecipe,
|
|
42
|
+
slotRecipe: defineSafeSlotRecipe,
|
|
43
|
+
textStyle: (definition: TextStyle) => definition,
|
|
44
|
+
styles: (styles: CodegenSystemStyleObject) => styles as SystemStyleObject,
|
|
45
|
+
textStyles: (defs: Recursive<Token<TextStyle>>) => defs as TextStyles,
|
|
46
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ObjectKeys<T extends Record<PropertyKey, unknown>> =
|
|
2
|
+
`${Exclude<keyof T, symbol>}`
|
|
3
|
+
|
|
4
|
+
export function objectKeys<T extends Record<PropertyKey, unknown>>(
|
|
5
|
+
obj: T,
|
|
6
|
+
): Array<ObjectKeys<T>> {
|
|
7
|
+
return Object.keys(obj) as Array<ObjectKeys<T>>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function objectValues<T extends Record<PropertyKey, unknown>>(
|
|
11
|
+
obj: T,
|
|
12
|
+
): Array<T[ObjectKeys<T>]> {
|
|
13
|
+
return Object.values(obj) as Array<T[ObjectKeys<T>]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function objectEntries<T extends Record<PropertyKey, unknown>>(
|
|
17
|
+
obj: T,
|
|
18
|
+
): Array<[ObjectKeys<T>, T[ObjectKeys<T>]]> {
|
|
19
|
+
return Object.entries(obj) as Array<[ObjectKeys<T>, T[ObjectKeys<T>]]>
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|