sparkle-design 0.9.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 (125) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.en.md +275 -0
  4. package/README.md +328 -0
  5. package/dist/components/ui/badge/index.d.ts +67 -0
  6. package/dist/components/ui/badge/index.figma.d.ts +1 -0
  7. package/dist/components/ui/badge/index.figma.js +28 -0
  8. package/dist/components/ui/badge/index.js +129 -0
  9. package/dist/components/ui/breadcrumb/index.d.ts +70 -0
  10. package/dist/components/ui/breadcrumb/index.figma.d.ts +1 -0
  11. package/dist/components/ui/breadcrumb/index.figma.js +28 -0
  12. package/dist/components/ui/breadcrumb/index.js +96 -0
  13. package/dist/components/ui/button/index.d.ts +145 -0
  14. package/dist/components/ui/button/index.figma.d.ts +1 -0
  15. package/dist/components/ui/button/index.figma.js +59 -0
  16. package/dist/components/ui/button/index.js +375 -0
  17. package/dist/components/ui/card/index.d.ts +193 -0
  18. package/dist/components/ui/card/index.figma.d.ts +1 -0
  19. package/dist/components/ui/card/index.figma.js +28 -0
  20. package/dist/components/ui/card/index.js +219 -0
  21. package/dist/components/ui/checkbox/index.d.ts +62 -0
  22. package/dist/components/ui/checkbox/index.figma.d.ts +1 -0
  23. package/dist/components/ui/checkbox/index.figma.js +34 -0
  24. package/dist/components/ui/checkbox/index.js +192 -0
  25. package/dist/components/ui/dialog/index.d.ts +106 -0
  26. package/dist/components/ui/dialog/index.figma.d.ts +1 -0
  27. package/dist/components/ui/dialog/index.figma.js +21 -0
  28. package/dist/components/ui/dialog/index.js +157 -0
  29. package/dist/components/ui/divider/index.d.ts +44 -0
  30. package/dist/components/ui/divider/index.figma.d.ts +1 -0
  31. package/dist/components/ui/divider/index.figma.js +39 -0
  32. package/dist/components/ui/divider/index.js +81 -0
  33. package/dist/components/ui/form/index.d.ts +171 -0
  34. package/dist/components/ui/form/index.figma.d.ts +1 -0
  35. package/dist/components/ui/form/index.figma.js +129 -0
  36. package/dist/components/ui/form/index.js +214 -0
  37. package/dist/components/ui/form/label.d.ts +4 -0
  38. package/dist/components/ui/form/label.js +20 -0
  39. package/dist/components/ui/icon/index.d.ts +71 -0
  40. package/dist/components/ui/icon/index.figma.d.ts +1 -0
  41. package/dist/components/ui/icon/index.figma.js +1858 -0
  42. package/dist/components/ui/icon/index.js +57 -0
  43. package/dist/components/ui/icon-button/index.d.ts +77 -0
  44. package/dist/components/ui/icon-button/index.figma.d.ts +1 -0
  45. package/dist/components/ui/icon-button/index.figma.js +43 -0
  46. package/dist/components/ui/icon-button/index.js +341 -0
  47. package/dist/components/ui/inline-message/index.d.ts +83 -0
  48. package/dist/components/ui/inline-message/index.figma.d.ts +1 -0
  49. package/dist/components/ui/inline-message/index.figma.js +26 -0
  50. package/dist/components/ui/inline-message/index.js +154 -0
  51. package/dist/components/ui/input/index.d.ts +118 -0
  52. package/dist/components/ui/input/index.figma.d.ts +1 -0
  53. package/dist/components/ui/input/index.figma.js +36 -0
  54. package/dist/components/ui/input/index.js +256 -0
  55. package/dist/components/ui/input-password/index.d.ts +27 -0
  56. package/dist/components/ui/input-password/index.figma.d.ts +1 -0
  57. package/dist/components/ui/input-password/index.figma.js +36 -0
  58. package/dist/components/ui/input-password/index.js +35 -0
  59. package/dist/components/ui/link/index.d.ts +68 -0
  60. package/dist/components/ui/link/index.figma.d.ts +1 -0
  61. package/dist/components/ui/link/index.figma.js +22 -0
  62. package/dist/components/ui/link/index.js +92 -0
  63. package/dist/components/ui/modal/index.d.ts +83 -0
  64. package/dist/components/ui/modal/index.figma.d.ts +1 -0
  65. package/dist/components/ui/modal/index.figma.js +61 -0
  66. package/dist/components/ui/modal/index.js +143 -0
  67. package/dist/components/ui/overlay/index.d.ts +19 -0
  68. package/dist/components/ui/overlay/index.figma.d.ts +1 -0
  69. package/dist/components/ui/overlay/index.figma.js +14 -0
  70. package/dist/components/ui/overlay/index.js +39 -0
  71. package/dist/components/ui/radio/index.d.ts +94 -0
  72. package/dist/components/ui/radio/index.figma.d.ts +1 -0
  73. package/dist/components/ui/radio/index.figma.js +63 -0
  74. package/dist/components/ui/radio/index.js +204 -0
  75. package/dist/components/ui/select/index.d.ts +175 -0
  76. package/dist/components/ui/select/index.figma.d.ts +1 -0
  77. package/dist/components/ui/select/index.figma.js +30 -0
  78. package/dist/components/ui/select/index.js +281 -0
  79. package/dist/components/ui/skeleton/index.d.ts +21 -0
  80. package/dist/components/ui/skeleton/index.figma.d.ts +1 -0
  81. package/dist/components/ui/skeleton/index.figma.js +14 -0
  82. package/dist/components/ui/skeleton/index.js +32 -0
  83. package/dist/components/ui/slider/index.d.ts +75 -0
  84. package/dist/components/ui/slider/index.figma.d.ts +1 -0
  85. package/dist/components/ui/slider/index.figma.js +28 -0
  86. package/dist/components/ui/slider/index.js +113 -0
  87. package/dist/components/ui/slider/utils.d.ts +16 -0
  88. package/dist/components/ui/slider/utils.js +56 -0
  89. package/dist/components/ui/spinner/index.d.ts +42 -0
  90. package/dist/components/ui/spinner/index.figma.d.ts +1 -0
  91. package/dist/components/ui/spinner/index.figma.js +16 -0
  92. package/dist/components/ui/spinner/index.js +51 -0
  93. package/dist/components/ui/switch/index.d.ts +46 -0
  94. package/dist/components/ui/switch/index.figma.d.ts +1 -0
  95. package/dist/components/ui/switch/index.figma.js +27 -0
  96. package/dist/components/ui/switch/index.js +75 -0
  97. package/dist/components/ui/tabs/index.d.ts +53 -0
  98. package/dist/components/ui/tabs/index.figma.d.ts +1 -0
  99. package/dist/components/ui/tabs/index.figma.js +55 -0
  100. package/dist/components/ui/tabs/index.js +164 -0
  101. package/dist/components/ui/tag/index.d.ts +50 -0
  102. package/dist/components/ui/tag/index.figma.d.ts +1 -0
  103. package/dist/components/ui/tag/index.figma.js +32 -0
  104. package/dist/components/ui/tag/index.js +177 -0
  105. package/dist/components/ui/textarea/index.d.ts +49 -0
  106. package/dist/components/ui/textarea/index.figma.d.ts +1 -0
  107. package/dist/components/ui/textarea/index.figma.js +27 -0
  108. package/dist/components/ui/textarea/index.js +94 -0
  109. package/dist/components/ui/toast/index.d.ts +60 -0
  110. package/dist/components/ui/toast/index.figma.d.ts +1 -0
  111. package/dist/components/ui/toast/index.figma.js +26 -0
  112. package/dist/components/ui/toast/index.js +57 -0
  113. package/dist/components/ui/tooltip/index.d.ts +52 -0
  114. package/dist/components/ui/tooltip/index.figma.d.ts +1 -0
  115. package/dist/components/ui/tooltip/index.figma.js +23 -0
  116. package/dist/components/ui/tooltip/index.js +65 -0
  117. package/dist/index.d.ts +27 -0
  118. package/dist/index.js +27 -0
  119. package/dist/lib/utils.d.ts +2 -0
  120. package/dist/lib/utils.js +5 -0
  121. package/dist/test/helpers.d.ts +56 -0
  122. package/dist/test/helpers.js +182 -0
  123. package/dist/test/setup.d.ts +1 -0
  124. package/dist/test/setup.js +38 -0
  125. package/package.json +253 -0
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Copyright 2026 Goodpatch Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ "use client";
6
+ var __rest = (this && this.__rest) || function (s, e) {
7
+ var t = {};
8
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
9
+ t[p] = s[p];
10
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
11
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
12
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
13
+ t[p[i]] = s[p[i]];
14
+ }
15
+ return t;
16
+ };
17
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ import { Select as SelectPrimitive } from "radix-ui";
19
+ import { Icon } from "../../../components/ui/icon/index.js";
20
+ import { cva } from "class-variance-authority";
21
+ import { cn } from "../../../lib/utils.js";
22
+ const selectTriggerVariants = cva([
23
+ "flex items-center justify-between w-full rounded-action border bg-white text-text-high transition-colors",
24
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-ring-normal)] focus-visible:ring-offset-2",
25
+ "overflow-hidden whitespace-nowrap",
26
+ ].join(" "), {
27
+ variants: {
28
+ size: {
29
+ sm: "h-8 py-1 pl-2 pr-1 gap-2 character-2-regular-pro",
30
+ md: "h-10 py-1 pl-3 pr-1.5 gap-2 character-3-regular-pro",
31
+ lg: "h-12 py-1 pl-4 pr-2 gap-2 character-4-regular-pro",
32
+ },
33
+ isInvalid: {
34
+ true: "bg-white border-negative-500 hover:border-negative-600 data-[state=open]:border-negative-600",
35
+ false: "border-neutral-500 hover:border-neutral-600 data-[state=open]:border-neutral-600",
36
+ },
37
+ isDisabled: {
38
+ true: "cursor-not-allowed bg-neutral-50 border-neutral-200 hover:border-neutral-200 text-text-disabled",
39
+ false: "cursor-pointer",
40
+ },
41
+ },
42
+ compoundVariants: [
43
+ {
44
+ isInvalid: true,
45
+ isDisabled: true,
46
+ class: "bg-neutral-50 border-negative-200 hover:border-negative-200",
47
+ },
48
+ ],
49
+ defaultVariants: {
50
+ size: "md",
51
+ isInvalid: false,
52
+ isDisabled: false,
53
+ },
54
+ });
55
+ const selectIconVariants = cva("", {
56
+ variants: {
57
+ size: {
58
+ sm: "icon-5-fill-0",
59
+ md: "icon-6-fill-0",
60
+ lg: "icon-7-fill-0",
61
+ },
62
+ isDisabled: {
63
+ true: "text-text-disabled",
64
+ false: "text-neutral-700",
65
+ },
66
+ },
67
+ defaultVariants: {
68
+ size: "md",
69
+ isDisabled: false,
70
+ },
71
+ });
72
+ const selectContentVariants = cva([
73
+ "bg-white text-text-high",
74
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
75
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
76
+ "relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-action border shadow-float",
77
+ ].join(" "), {
78
+ variants: {
79
+ position: {
80
+ popper: "bg-white data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
81
+ item: "",
82
+ "item-aligned": "",
83
+ },
84
+ },
85
+ defaultVariants: {
86
+ position: "popper",
87
+ },
88
+ });
89
+ const selectViewportVariants = cva("p-1", {
90
+ variants: {
91
+ position: {
92
+ popper: "h-[var(--radix-select-content-available-height)] w-full min-w-[var(--radix-select-trigger-width)]",
93
+ item: "",
94
+ "item-aligned": "",
95
+ },
96
+ },
97
+ defaultVariants: {
98
+ position: "popper",
99
+ },
100
+ });
101
+ /**
102
+ * **概要 / Overview**
103
+ *
104
+ * - セレクトはオプショングループの中から値を選択する形式でユーザーからの入力を取得するために使用するコンポーネントです。
105
+ * - en: The Select component is used to capture user input by selecting a value from a group of options.
106
+ *
107
+ * **アンチパターン / Anti-patterns**
108
+ *
109
+ * - `SelectTrigger` と横並びの Button は原則同じサイズにしてください。デフォルトの `SelectTrigger` に対しては `Button size="md"` を使ってください。
110
+ * en: Keep Button size aligned when placing it next to `SelectTrigger`. Use `Button size="md"` with the default `SelectTrigger` size.
111
+ *
112
+ * ```tsx
113
+ * // ✅ Correct
114
+ * <div className="flex gap-2">
115
+ * <Select>
116
+ * <SelectTrigger size="md" className="w-60">
117
+ * <SelectValue placeholder="選択してください" />
118
+ * </SelectTrigger>
119
+ * </Select>
120
+ * <Button size="md">追加</Button>
121
+ * </div>
122
+ *
123
+ * // ❌ Wrong - 高さが揃わないサイズ不一致
124
+ * <div className="flex gap-2">
125
+ * <Select>
126
+ * <SelectTrigger size="md" className="w-60">
127
+ * <SelectValue placeholder="選択してください" />
128
+ * </SelectTrigger>
129
+ * </Select>
130
+ * <Button size="sm">追加</Button>
131
+ * </div>
132
+ * ```
133
+
134
+ * **使用例 / Usage Example**
135
+ *
136
+ * ```tsx
137
+ * <Select>
138
+ * <SelectTrigger size="md">
139
+ * <SelectValue placeholder="選択してください" />
140
+ * </SelectTrigger>
141
+ * <SelectContent>
142
+ * <SelectItem value="option1">オプション1</SelectItem>
143
+ * <SelectItem value="option2">オプション2</SelectItem>
144
+ * </SelectContent>
145
+ * </Select>
146
+ * ```
147
+ *
148
+ * @param {React.ComponentProps<typeof SelectPrimitive.Root>} props
149
+ */
150
+ function Select(_a) {
151
+ var props = __rest(_a, []);
152
+ return _jsx(SelectPrimitive.Root, Object.assign({ "data-slot": "select" }, props));
153
+ }
154
+ function SelectGroup(_a) {
155
+ var props = __rest(_a, []);
156
+ return _jsx(SelectPrimitive.Group, Object.assign({ "data-slot": "select-group" }, props));
157
+ }
158
+ function SelectValue(_a) {
159
+ var props = __rest(_a, []);
160
+ return _jsx(SelectPrimitive.Value, Object.assign({ "data-slot": "select-value" }, props));
161
+ }
162
+ /**
163
+ * **概要 / Overview**
164
+ *
165
+ * - セレクトのトリガー部分で、クリックで選択肢リストを開閉するボタンとして機能します。
166
+ * - en: The trigger part of the select that functions as a button to open/close the option list when clicked.
167
+ *
168
+ * @param {SelectTriggerProps} props
169
+ */
170
+ function SelectTrigger(_a) {
171
+ var { className, size, children, isInvalid, disabled } = _a, props = __rest(_a, ["className", "size", "children", "isInvalid", "disabled"]);
172
+ return (_jsxs(SelectPrimitive.Trigger, Object.assign({ "data-slot": "select-trigger", "data-size": size, "aria-invalid": isInvalid || undefined, className: cn(selectTriggerVariants({
173
+ size,
174
+ isInvalid,
175
+ isDisabled: disabled,
176
+ }), className), disabled: disabled }, props, { children: [_jsx("span", { className: "flex-1 min-w-0 text-left truncate", children: children }), _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(Icon, { icon: "arrow_drop_down", className: cn(selectIconVariants({ size, isDisabled: disabled }), "shrink-0") }) })] })));
177
+ }
178
+ /**
179
+ * **概要 / Overview**
180
+ *
181
+ * - セレクトのドロップダウンリスト本体で、選択肢リストの表示・スクロール制御を行います。
182
+ * - en: The main dropdown list body of the select that handles display and scroll control of option lists.
183
+ *
184
+ * **使用例 / Usage Example**
185
+ *
186
+ * ```tsx
187
+ * <SelectContent>
188
+ * <SelectItem value="option1">オプション1</SelectItem>
189
+ * </SelectContent>
190
+ * ```
191
+ */
192
+ function SelectContent(_a) {
193
+ var { className, children, position = "popper" } = _a, props = __rest(_a, ["className", "children", "position"]);
194
+ return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, Object.assign({ "data-slot": "select-content", className: cn(selectContentVariants({ position }), className), position: position }, props, { children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { className: cn(selectViewportVariants({ position })), children: children }), _jsx(SelectScrollDownButton, {})] })) }));
195
+ }
196
+ /**
197
+ * **概要 / Overview**
198
+ *
199
+ * - セレクトのラベル部分で、グループ化された選択肢のラベル表示に使います。
200
+ * - en: The label part of the select used to display labels for grouped options.
201
+ *
202
+ * **使用例 / Usage Example**
203
+ *
204
+ * ```tsx
205
+ * <SelectLabel>カテゴリー</SelectLabel>
206
+ * ```
207
+ */
208
+ function SelectLabel(_a) {
209
+ var { className } = _a, props = __rest(_a, ["className"]);
210
+ return (_jsx(SelectPrimitive.Label, Object.assign({ "data-slot": "select-label", className: cn("px-2 py-1.5 character-1-bold-pro text-text-high", className) }, props)));
211
+ }
212
+ /**
213
+ * **概要 / Overview**
214
+ *
215
+ * - セレクトの各選択肢アイテムで、選択可能なリスト項目として機能します。
216
+ * - en: Each selectable item in the select that functions as a selectable list item.
217
+ *
218
+ * **使用例 / Usage Example**
219
+ *
220
+ * ```tsx
221
+ * <SelectItem value="option1">オプション1</SelectItem>
222
+ * ```
223
+ */
224
+ function SelectItem(_a) {
225
+ var { className, children, textClassName } = _a, props = __rest(_a, ["className", "children", "textClassName"]);
226
+ return (_jsxs(SelectPrimitive.Item, Object.assign({ "data-slot": "select-item", className: cn([
227
+ "relative flex w-full cursor-pointer select-none items-center rounded-notice",
228
+ "py-1.5 pl-8 pr-2 text-sm",
229
+ "character-1-regular-pro text-neutral-700",
230
+ "outline-none focus:bg-neutral-100 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
231
+ ].join(" "), className) }, props, { children: [_jsx(SelectPrimitive.ItemIndicator, { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(Icon, { icon: "check", size: 4 }) }), _jsx(SelectPrimitive.ItemText, { className: cn("flex-1", textClassName), children: children })] })));
232
+ }
233
+ /**
234
+ * **概要 / Overview**
235
+ *
236
+ * - セレクトの区切り線で、選択肢リスト内の区切り表示に使います。
237
+ * - en: The separator line in the select used to display divisions within the option list.
238
+ *
239
+ * **使用例 / Usage Example**
240
+ *
241
+ * ```tsx
242
+ * <SelectSeparator />
243
+ * ```
244
+ */
245
+ function SelectSeparator(_a) {
246
+ var { className } = _a, props = __rest(_a, ["className"]);
247
+ return (_jsx(SelectPrimitive.Separator, Object.assign({ "data-slot": "select-separator", className: cn("-mx-1 my-1 h-px bg-divider-low", className) }, props)));
248
+ }
249
+ /**
250
+ * **概要 / Overview**
251
+ *
252
+ * - セレクトの上スクロールボタンで、選択肢が多い場合にリストを上方向にスクロールします。
253
+ * - en: The up scroll button of the select that scrolls the list upward when there are many options.
254
+ *
255
+ * **使用例 / Usage Example**
256
+ *
257
+ * ```tsx
258
+ * <SelectScrollUpButton />
259
+ * ```
260
+ */
261
+ function SelectScrollUpButton(_a) {
262
+ var { className } = _a, props = __rest(_a, ["className"]);
263
+ return (_jsx(SelectPrimitive.ScrollUpButton, Object.assign({ "data-slot": "select-scroll-up-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_less", size: 4 }) })));
264
+ }
265
+ /**
266
+ * **概要 / Overview**
267
+ *
268
+ * - セレクトの下スクロールボタンで、選択肢が多い場合にリストを下方向にスクロールします。
269
+ * - en: The down scroll button of the select that scrolls the list downward when there are many options.
270
+ *
271
+ * **使用例 / Usage Example**
272
+ *
273
+ * ```tsx
274
+ * <SelectScrollDownButton />
275
+ * ```
276
+ */
277
+ function SelectScrollDownButton(_a) {
278
+ var { className } = _a, props = __rest(_a, ["className"]);
279
+ return (_jsx(SelectPrimitive.ScrollDownButton, Object.assign({ "data-slot": "select-scroll-down-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_more", size: 4 }) })));
280
+ }
281
+ export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright 2026 Goodpatch Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import React from "react";
6
+ /**
7
+ * **概要 / Overview**
8
+ *
9
+ * - スケルトンはユーザーにコンテンツが読込中であることを提示するために使用するコンポーネントです。
10
+ * - en: The Skeleton component is used to indicate to users that content is loading.
11
+ *
12
+ * **使用例 / Usage Example**
13
+ *
14
+ * ```tsx
15
+ * <Skeleton className="h-4 w-[250px]" />
16
+ * ```
17
+ *
18
+ * @param {React.HTMLAttributes<HTMLDivElement>} props
19
+ */
20
+ declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
21
+ export { Skeleton };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import figma from "@figma/code-connect";
3
+ import { Skeleton } from "./index.js";
4
+ /**
5
+ * -- This file was auto-generated by Code Connect --
6
+ * None of your props could be automatically mapped to Figma properties.
7
+ * You should update the `props` object to include a mapping from your
8
+ * code props to Figma properties, and update the `example` function to
9
+ * return the code example you'd like to see in Figma
10
+ */
11
+ figma.connect(Skeleton, "https://www.figma.com/design/7alBZXZf65YgcII41TWT0r/Sparkle-Design?node-id=24%3A131", {
12
+ props: {},
13
+ example: props => _jsx(Skeleton, {}),
14
+ });
@@ -0,0 +1,32 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { cn } from "../../../lib/utils.js";
14
+ /**
15
+ * **概要 / Overview**
16
+ *
17
+ * - スケルトンはユーザーにコンテンツが読込中であることを提示するために使用するコンポーネントです。
18
+ * - en: The Skeleton component is used to indicate to users that content is loading.
19
+ *
20
+ * **使用例 / Usage Example**
21
+ *
22
+ * ```tsx
23
+ * <Skeleton className="h-4 w-[250px]" />
24
+ * ```
25
+ *
26
+ * @param {React.HTMLAttributes<HTMLDivElement>} props
27
+ */
28
+ function Skeleton(_a) {
29
+ var { className } = _a, props = __rest(_a, ["className"]);
30
+ return (_jsx("div", Object.assign({ className: cn("animate-pulse rounded-notice bg-skeleton-fill", className) }, props)));
31
+ }
32
+ export { Skeleton };
@@ -0,0 +1,75 @@
1
+ import * as React from "react";
2
+ import { Slider as SliderPrimitive } from "radix-ui";
3
+ import { type VariantProps } from "class-variance-authority";
4
+ declare const sliderRootVariants: (props?: ({
5
+ isDisabled?: boolean | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ type SliderVariantProps = VariantProps<typeof sliderRootVariants>;
8
+ type SliderPrimitiveProps = Omit<React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, "orientation">;
9
+ export interface SliderProps extends SliderPrimitiveProps {
10
+ /**
11
+ * スライダーが無効化されているかどうか
12
+ * en: Whether the slider is disabled
13
+ */
14
+ isDisabled?: SliderVariantProps["isDisabled"];
15
+ /**
16
+ * スライダーの最大値
17
+ * en: The maximum value of the slider
18
+ */
19
+ max?: SliderPrimitiveProps["max"];
20
+ /**
21
+ * スライダーの最小値
22
+ * en: The minimum value of the slider
23
+ */
24
+ min?: SliderPrimitiveProps["min"];
25
+ /**
26
+ * スライダーのステップ値
27
+ * en: The step value of the slider
28
+ */
29
+ step?: SliderPrimitiveProps["step"];
30
+ /**
31
+ * スライダーの値(制御コンポーネント用)
32
+ * en: The value of the slider (for controlled component)
33
+ */
34
+ value?: SliderPrimitiveProps["value"];
35
+ /**
36
+ * スライダーの初期値(非制御コンポーネント用)
37
+ * en: The default value of the slider (for uncontrolled component)
38
+ */
39
+ defaultValue?: SliderPrimitiveProps["defaultValue"];
40
+ /**
41
+ * スライダーの値が変更されたときに呼び出されるコールバック
42
+ * en: Callback invoked when the value of the slider changes
43
+ */
44
+ onValueChange?: SliderPrimitiveProps["onValueChange"];
45
+ /**
46
+ * スライダーの単位表示を設定
47
+ * en: Set the unit display of the slider
48
+ */
49
+ unit?: string;
50
+ }
51
+ /**
52
+ * **概要 / Overview**
53
+ *
54
+ * - スライダーは任意の範囲の中からユーザーに特定の数値を選択してもらうために使用するコンポーネントです。
55
+ * - en: The Slider component is used to select a value within a range.
56
+ *
57
+ * **使用例 / Usage Example**
58
+ *
59
+ * ```tsx
60
+ * <Slider
61
+ * value={[50]}
62
+ * onValueChange={setValue}
63
+ * min={0}
64
+ * max={100}
65
+ * step={1}
66
+ * />
67
+ * ```
68
+ *
69
+ * @param {SliderProps} props
70
+ */
71
+ declare function Slider({ className, isDisabled, disabled, value, defaultValue, onValueChange, unit, ...props }: SliderProps): import("react/jsx-runtime").JSX.Element;
72
+ declare namespace Slider {
73
+ var displayName: string | undefined;
74
+ }
75
+ export { Slider };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import figma from "@figma/code-connect";
3
+ import { Slider } from "./index.js";
4
+ /**
5
+ * -- This file was auto-generated by Code Connect --
6
+ * `props` includes a mapping from your code props to Figma properties.
7
+ * You should check this is correct, and update the `example` function
8
+ * to return the code example you'd like to see in Figma
9
+ */
10
+ figma.connect(Slider, "https://www.figma.com/design/7alBZXZf65YgcII41TWT0r/Sparkle-Design?node-id=15094%3A965", {
11
+ props: {
12
+ // These props were automatically mapped based on your linked code:
13
+ disabled: figma.enum("state", {
14
+ disabled: true,
15
+ }),
16
+ // No matching props could be found for these Figma properties:
17
+ // "value": figma.string('value'),
18
+ // "position": figma.enum('position', {
19
+ // "0%": "0-",
20
+ // "20%": "20-",
21
+ // "40%": "40-",
22
+ // "60%": "60-",
23
+ // "80%": "80-",
24
+ // "100%": "100-"
25
+ // })
26
+ },
27
+ example: props => _jsx(Slider, { disabled: props.disabled }),
28
+ });
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Copyright 2026 Goodpatch Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ "use client";
6
+ var __rest = (this && this.__rest) || function (s, e) {
7
+ var t = {};
8
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
9
+ t[p] = s[p];
10
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
11
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
12
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
13
+ t[p[i]] = s[p[i]];
14
+ }
15
+ return t;
16
+ };
17
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ import * as React from "react";
19
+ import { Slider as SliderPrimitive } from "radix-ui";
20
+ import { cva } from "class-variance-authority";
21
+ import { cn } from "../../../lib/utils.js";
22
+ import { getIndicatorMinCh } from "./utils.js";
23
+ const sliderRootVariants = cva("relative flex touch-none select-none items-center py-1.5 flex-1 min-w-0", {
24
+ variants: {
25
+ isDisabled: {
26
+ true: "cursor-not-allowed",
27
+ },
28
+ },
29
+ defaultVariants: {
30
+ isDisabled: false,
31
+ },
32
+ });
33
+ const sliderRangeVariants = cva("absolute h-full bg-primary-500", {
34
+ variants: {
35
+ isDisabled: {
36
+ true: "bg-neutral-200",
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ isDisabled: false,
41
+ },
42
+ });
43
+ const sliderThumbVariants = cva([
44
+ "relative block rounded-full border border-neutral-500 bg-white shadow-raise cursor-pointer",
45
+ "ring-offset-background transition-colors hover:bg-neutral-100",
46
+ "focus:outline-hidden focus:bg-primary-100 focus:border-primary-200",
47
+ "focus:ring-2 focus:ring-[var(--color-ring-normal)] focus:ring-offset-2",
48
+ "h-4 w-4",
49
+ // タッチターゲットを24x24px以上に拡張(WCAG 2.5.8)
50
+ // en: Expand touch target to 24x24px minimum (WCAG 2.5.8)
51
+ "before:absolute before:content-[''] before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:min-h-6 before:min-w-6",
52
+ ].join(" "), {
53
+ variants: {
54
+ isDisabled: {
55
+ true: "pointer-events-none bg-neutral-100 hover:bg-neutral-100 border-none cursor-not-allowed",
56
+ },
57
+ },
58
+ defaultVariants: {
59
+ isDisabled: false,
60
+ },
61
+ });
62
+ /**
63
+ * **概要 / Overview**
64
+ *
65
+ * - スライダーは任意の範囲の中からユーザーに特定の数値を選択してもらうために使用するコンポーネントです。
66
+ * - en: The Slider component is used to select a value within a range.
67
+ *
68
+ * **使用例 / Usage Example**
69
+ *
70
+ * ```tsx
71
+ * <Slider
72
+ * value={[50]}
73
+ * onValueChange={setValue}
74
+ * min={0}
75
+ * max={100}
76
+ * step={1}
77
+ * />
78
+ * ```
79
+ *
80
+ * @param {SliderProps} props
81
+ */
82
+ function Slider(_a) {
83
+ var _b;
84
+ var { className, isDisabled, disabled, value, defaultValue, onValueChange, unit } = _a, props = __rest(_a, ["className", "isDisabled", "disabled", "value", "defaultValue", "onValueChange", "unit"]);
85
+ const isDisabledState = Boolean(isDisabled || disabled);
86
+ // 非制御コンポーネントの場合の内部状態管理
87
+ const [internalValue, setInternalValue] = React.useState(defaultValue || [(_b = props === null || props === void 0 ? void 0 : props.min) !== null && _b !== void 0 ? _b : 0]);
88
+ // 制御コンポーネントかどうかを判定
89
+ const isControlled = value !== undefined;
90
+ // 現在の値を取得(制御/非制御コンポーネントに対応)
91
+ const currentValue = isControlled ? value : internalValue;
92
+ // 値変更ハンドラー
93
+ const handleValueChange = React.useCallback((newValue) => {
94
+ if (!isControlled) {
95
+ setInternalValue(newValue);
96
+ }
97
+ onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(newValue);
98
+ }, [isControlled, onValueChange]);
99
+ // 最小幅のみ制御するため style のみ指定
100
+ // en: Control only min width
101
+ const valueMinWidthStyle = React.useMemo(() => {
102
+ const ch = getIndicatorMinCh(props === null || props === void 0 ? void 0 : props.max, unit);
103
+ // NOTE: 端にThumbが来た時サイズ変化してしまうため、Thumbの半径分の余白を加算
104
+ return ch > 0 ? { minWidth: `calc(${ch}ch + var(--spacing) * 2)` } : {};
105
+ }, [props === null || props === void 0 ? void 0 : props.max, unit]);
106
+ return (_jsxs("div", { className: "flex justify-center gap-3 w-full", children: [_jsxs(SliderPrimitive.Root, Object.assign({ "data-slot": "slider", disabled: isDisabledState, "aria-disabled": isDisabledState, className: cn(sliderRootVariants({ isDisabled: isDisabledState }), className), value: value, defaultValue: defaultValue, onValueChange: handleValueChange }, props, { children: [_jsx(SliderPrimitive.Track, { "data-slot": "slider-track", className: cn("relative w-full grow overflow-hidden rounded-xs h-1", isDisabledState
107
+ ? "bg-neutral-100 cursor-not-allowed"
108
+ : "bg-neutral-200 cursor-pointer"), children: _jsx(SliderPrimitive.Range, { "data-slot": "slider-range", className: cn(sliderRangeVariants({ isDisabled: isDisabledState })) }) }), _jsx(SliderPrimitive.Thumb, { "data-slot": "slider-thumb", className: cn(sliderThumbVariants({ isDisabled: isDisabledState })) })] })), _jsxs("span", { className: cn("text-right tabular-nums character-3-regular-mono flex-shrink-0", isDisabledState
109
+ ? "text-text-disabled cursor-not-allowed"
110
+ : "text-text-middle"), style: valueMinWidthStyle, children: [currentValue[0], unit] })] }));
111
+ }
112
+ Slider.displayName = SliderPrimitive.Root.displayName;
113
+ export { Slider };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 数値の桁数を算出(符号・小数点は除外)
3
+ * en: Count digits of a number (exclude sign and decimal part)
4
+ */
5
+ export declare function getDigitCount(max?: number): number;
6
+ /**
7
+ * 単位の見かけ幅(ch)を概算
8
+ * 全角/CJKや絵文字は 2ch、それ以外は 1ch として加算
9
+ * en: Approximate visual width of unit in ch. Count full-width/CJK and emoji as 2ch, others as 1ch
10
+ */
11
+ export declare function getUnitChWidth(unit?: string): number;
12
+ /**
13
+ * 値インディケーターの最小幅(ch)を算出
14
+ * en: Calculate the min ch width for the value indicator
15
+ */
16
+ export declare function getIndicatorMinCh(max?: number, unit?: string): number;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 数値の桁数を算出(符号・小数点は除外)
3
+ * en: Count digits of a number (exclude sign and decimal part)
4
+ */
5
+ export function getDigitCount(max) {
6
+ const maxVal = max !== null && max !== void 0 ? max : 100;
7
+ const digits = Math.abs(Math.trunc(maxVal))
8
+ .toString()
9
+ .replace(/\D/g, "").length;
10
+ return Math.max(1, digits);
11
+ }
12
+ /**
13
+ * 単位の見かけ幅(ch)を概算
14
+ * 全角/CJKや絵文字は 2ch、それ以外は 1ch として加算
15
+ * en: Approximate visual width of unit in ch. Count full-width/CJK and emoji as 2ch, others as 1ch
16
+ */
17
+ export function getUnitChWidth(unit) {
18
+ if (!unit)
19
+ return 0;
20
+ const isFullwidth = (codePoint) => {
21
+ if (codePoint >= 0x1100 &&
22
+ (codePoint <= 0x115f ||
23
+ codePoint === 0x2329 ||
24
+ codePoint === 0x232a ||
25
+ (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
26
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
27
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
28
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
29
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
30
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
31
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
32
+ (codePoint >= 0x1b000 && codePoint <= 0x1b001) ||
33
+ (codePoint >= 0x1f200 && codePoint <= 0x1f251) ||
34
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd))) {
35
+ return true;
36
+ }
37
+ return false;
38
+ };
39
+ const isEmoji = (codePoint) => (codePoint >= 0x1f000 && codePoint <= 0x1fbff) ||
40
+ (codePoint >= 0x1f900 && codePoint <= 0x1f9ff);
41
+ let width = 0;
42
+ for (const ch of [...unit]) {
43
+ const cp = ch.codePointAt(0);
44
+ if (cp === undefined)
45
+ continue;
46
+ width += isFullwidth(cp) || isEmoji(cp) ? 2 : 1;
47
+ }
48
+ return width;
49
+ }
50
+ /**
51
+ * 値インディケーターの最小幅(ch)を算出
52
+ * en: Calculate the min ch width for the value indicator
53
+ */
54
+ export function getIndicatorMinCh(max, unit) {
55
+ return getDigitCount(max) + getUnitChWidth(unit);
56
+ }