@nexus-cross/design-system 1.0.10 → 1.0.12

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 (39) hide show
  1. package/cursor-rules/nexus-ui-api.mdc +27 -5
  2. package/dist/chunks/{chunk-CV4GMFWP.js → chunk-2WM23PO6.js} +5 -3
  3. package/dist/chunks/chunk-5J63FUAS.mjs +256 -0
  4. package/dist/chunks/{chunk-BMYFRG3M.mjs → chunk-BQ6GJJB6.mjs} +1 -1
  5. package/dist/chunks/{chunk-P73MEU7N.mjs → chunk-HI5XZ4PB.mjs} +5 -3
  6. package/dist/chunks/chunk-LAGQ7J5A.js +279 -0
  7. package/dist/chunks/{chunk-6MT6Y6OF.js → chunk-WXMMOQXZ.js} +1 -1
  8. package/dist/components/ImageUpload.d.ts +23 -0
  9. package/dist/components/ImageUpload.d.ts.map +1 -0
  10. package/dist/components/ToggleGroup.d.ts +2 -0
  11. package/dist/components/ToggleGroup.d.ts.map +1 -1
  12. package/dist/image-upload.js +16 -0
  13. package/dist/image-upload.mjs +3 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +25 -16
  17. package/dist/index.mjs +3 -2
  18. package/dist/schemas/_all.json +87 -0
  19. package/dist/schemas/image-upload.d.ts +45 -0
  20. package/dist/schemas/image-upload.d.ts.map +1 -0
  21. package/dist/schemas/imageUpload.json +83 -0
  22. package/dist/schemas/index.d.ts +1 -0
  23. package/dist/schemas/index.d.ts.map +1 -1
  24. package/dist/schemas/toggle-group.d.ts +3 -0
  25. package/dist/schemas/toggle-group.d.ts.map +1 -1
  26. package/dist/schemas/toggleGroup.json +4 -0
  27. package/dist/schemas.js +19 -0
  28. package/dist/schemas.mjs +19 -1
  29. package/dist/styles/.generated/built.d.ts +1 -1
  30. package/dist/styles/.generated/built.d.ts.map +1 -1
  31. package/dist/styles/layer.js +2 -2
  32. package/dist/styles/layer.mjs +1 -1
  33. package/dist/styles.css +269 -15
  34. package/dist/styles.js +2 -2
  35. package/dist/styles.layered.css +269 -15
  36. package/dist/styles.mjs +1 -1
  37. package/dist/toggle-group.js +3 -3
  38. package/dist/toggle-group.mjs +1 -1
  39. package/package.json +2 -2
@@ -22,7 +22,7 @@ var toggleGroupVariants = cva("nexus-toggle-group", {
22
22
  }
23
23
  });
24
24
  var ToggleGroup = React.forwardRef(
25
- ({ className, variant, size, items, disabled, ...props }, ref) => {
25
+ ({ className, variant, size, items, disabled, required, ...props }, ref) => {
26
26
  const rootRef = React.useRef(null);
27
27
  const [animated, setAnimated] = React.useState(false);
28
28
  const [pos, setPos] = React.useState(null);
@@ -75,21 +75,23 @@ var ToggleGroup = React.forwardRef(
75
75
  }, []);
76
76
  const handleSingleChange = React.useCallback(
77
77
  (val) => {
78
+ if (required && !val) return;
78
79
  setTrackedValue(val);
79
80
  if (props.type !== "multiple") {
80
81
  props.onValueChange?.(val);
81
82
  }
82
83
  },
83
- [props.type, props.onValueChange]
84
+ [props.type, props.onValueChange, required]
84
85
  );
85
86
  const handleMultipleChange = React.useCallback(
86
87
  (val) => {
88
+ if (required && val.length === 0) return;
87
89
  setTrackedValue(val);
88
90
  if (props.type === "multiple") {
89
91
  props.onValueChange?.(val);
90
92
  }
91
93
  },
92
- [props.type, props.onValueChange]
94
+ [props.type, props.onValueChange, required]
93
95
  );
94
96
  const rootProps = props.type === "multiple" ? {
95
97
  type: "multiple",
@@ -0,0 +1,279 @@
1
+ 'use strict';
2
+
3
+ var chunkCZC76ZD5_js = require('./chunk-CZC76ZD5.js');
4
+ var React = require('react');
5
+ var classVarianceAuthority = require('class-variance-authority');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
27
+
28
+ var imageUploadVariants = classVarianceAuthority.cva("nexus-image-upload", {
29
+ variants: {
30
+ size: {
31
+ sm: "nexus-image-upload--sm",
32
+ md: "nexus-image-upload--md",
33
+ lg: "nexus-image-upload--lg"
34
+ }
35
+ },
36
+ defaultVariants: { size: "md" }
37
+ });
38
+ var DEFAULT_ACCEPT = ["jpg", "jpeg", "png", "gif", "webp"];
39
+ var DEFAULT_MAX_SIZE = 2 * 1024 * 1024;
40
+ var ImageUpIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
41
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21" }),
42
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m13.5 19 3-3 3 3" }),
43
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 22v-6" }),
44
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "9", r: "2" })
45
+ ] });
46
+ var CloseIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 4L4 12M4 4l8 8" }) });
47
+ function formatBytes(bytes) {
48
+ if (bytes >= 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}MB`;
49
+ return `${Math.round(bytes / 1024)}KB`;
50
+ }
51
+ var ImageUpload = React__namespace.forwardRef(
52
+ ({
53
+ value: controlledValue,
54
+ defaultValue,
55
+ onChange,
56
+ onError,
57
+ accept = DEFAULT_ACCEPT,
58
+ maxSize = DEFAULT_MAX_SIZE,
59
+ placeholder = "\uC774\uBBF8\uC9C0\uB97C \uB4DC\uB798\uADF8\uD558\uAC70\uB098 \uD30C\uC77C \uC120\uD0DD",
60
+ formatDescription: formatDescProp,
61
+ label,
62
+ description,
63
+ disabled = false,
64
+ size,
65
+ className
66
+ }, ref) => {
67
+ const isControlled = controlledValue !== void 0;
68
+ const [internalPreview, setInternalPreview] = React__namespace.useState(
69
+ defaultValue ?? null
70
+ );
71
+ const preview = isControlled ? controlledValue : internalPreview;
72
+ const [isDragging, setIsDragging] = React__namespace.useState(false);
73
+ const inputRef = React__namespace.useRef(null);
74
+ const dragCounter = React__namespace.useRef(0);
75
+ const acceptMime = React__namespace.useMemo(
76
+ () => accept.map((ext) => {
77
+ const lower = ext.toLowerCase().replace(/^\./, "");
78
+ if (lower === "jpg" || lower === "jpeg") return "image/jpeg";
79
+ return `image/${lower}`;
80
+ }),
81
+ [accept]
82
+ );
83
+ const formatText = formatDescProp ?? `${[...new Set(accept.map((e) => e.toUpperCase().replace(/^\./, "")))].join(" \xB7 ")} \xB7 \uCD5C\uB300 ${formatBytes(maxSize)}`;
84
+ const validateFile = React__namespace.useCallback(
85
+ (file) => {
86
+ if (!acceptMime.includes(file.type)) {
87
+ return `\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD\uC785\uB2C8\uB2E4. (${accept.join(", ")})`;
88
+ }
89
+ if (file.size > maxSize) {
90
+ return `\uD30C\uC77C \uD06C\uAE30\uAC00 ${formatBytes(maxSize)}\uB97C \uCD08\uACFC\uD569\uB2C8\uB2E4.`;
91
+ }
92
+ return null;
93
+ },
94
+ [acceptMime, accept, maxSize]
95
+ );
96
+ const handleFile = React__namespace.useCallback(
97
+ (file) => {
98
+ const error = validateFile(file);
99
+ if (error) {
100
+ onError?.(error);
101
+ return;
102
+ }
103
+ if (!isControlled) {
104
+ const url = URL.createObjectURL(file);
105
+ setInternalPreview((prev) => {
106
+ if (prev?.startsWith("blob:")) URL.revokeObjectURL(prev);
107
+ return url;
108
+ });
109
+ }
110
+ onChange?.(file);
111
+ },
112
+ [validateFile, isControlled, onChange, onError]
113
+ );
114
+ const handleRemove = React__namespace.useCallback(() => {
115
+ if (!isControlled) {
116
+ setInternalPreview((prev) => {
117
+ if (prev?.startsWith("blob:")) URL.revokeObjectURL(prev);
118
+ return null;
119
+ });
120
+ }
121
+ onChange?.(null);
122
+ if (inputRef.current) inputRef.current.value = "";
123
+ }, [isControlled, onChange]);
124
+ const handleInputChange = React__namespace.useCallback(
125
+ (e) => {
126
+ const file = e.target.files?.[0];
127
+ if (file) handleFile(file);
128
+ },
129
+ [handleFile]
130
+ );
131
+ const handleClick = React__namespace.useCallback(() => {
132
+ if (!disabled) inputRef.current?.click();
133
+ }, [disabled]);
134
+ const handleDragEnter = React__namespace.useCallback(
135
+ (e) => {
136
+ e.preventDefault();
137
+ e.stopPropagation();
138
+ if (disabled) return;
139
+ dragCounter.current += 1;
140
+ if (dragCounter.current === 1) setIsDragging(true);
141
+ },
142
+ [disabled]
143
+ );
144
+ const handleDragLeave = React__namespace.useCallback((e) => {
145
+ e.preventDefault();
146
+ e.stopPropagation();
147
+ dragCounter.current -= 1;
148
+ if (dragCounter.current === 0) setIsDragging(false);
149
+ }, []);
150
+ const handleDragOver = React__namespace.useCallback((e) => {
151
+ e.preventDefault();
152
+ e.stopPropagation();
153
+ }, []);
154
+ const handleDrop = React__namespace.useCallback(
155
+ (e) => {
156
+ e.preventDefault();
157
+ e.stopPropagation();
158
+ setIsDragging(false);
159
+ dragCounter.current = 0;
160
+ if (disabled) return;
161
+ const file = e.dataTransfer.files?.[0];
162
+ if (file) handleFile(file);
163
+ },
164
+ [disabled, handleFile]
165
+ );
166
+ React__namespace.useEffect(() => {
167
+ return () => {
168
+ if (!isControlled && internalPreview?.startsWith("blob:")) {
169
+ URL.revokeObjectURL(internalPreview);
170
+ }
171
+ };
172
+ }, []);
173
+ const hasField = !!(label || description);
174
+ const hiddenInput = /* @__PURE__ */ jsxRuntime.jsx(
175
+ "input",
176
+ {
177
+ ref: inputRef,
178
+ type: "file",
179
+ accept: acceptMime.join(","),
180
+ onChange: handleInputChange,
181
+ className: "nexus-image-upload__input",
182
+ tabIndex: -1
183
+ }
184
+ );
185
+ const previewView = /* @__PURE__ */ jsxRuntime.jsxs(
186
+ "div",
187
+ {
188
+ className: chunkCZC76ZD5_js.cn(
189
+ "nexus-image-upload--has-preview",
190
+ size === "sm" && "nexus-image-upload--sm",
191
+ size === "lg" && "nexus-image-upload--lg",
192
+ disabled && "nexus-image-upload--disabled",
193
+ !hasField && className
194
+ ),
195
+ children: [
196
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nexus-image-upload__preview-area", children: [
197
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nexus-image-upload__preview-wrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
198
+ "img",
199
+ {
200
+ src: preview,
201
+ alt: "Uploaded preview",
202
+ className: "nexus-image-upload__preview"
203
+ }
204
+ ) }),
205
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx(
206
+ "button",
207
+ {
208
+ type: "button",
209
+ className: "nexus-image-upload__remove",
210
+ onClick: handleRemove,
211
+ "aria-label": "\uC774\uBBF8\uC9C0 \uC0AD\uC81C",
212
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "nexus-image-upload__remove-icon" })
213
+ }
214
+ )
215
+ ] }),
216
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nexus-image-upload__info", children: [
217
+ !disabled && /* @__PURE__ */ jsxRuntime.jsx(
218
+ "button",
219
+ {
220
+ type: "button",
221
+ className: "nexus-image-upload__change-btn",
222
+ onClick: handleClick,
223
+ children: "\uC774\uBBF8\uC9C0 \uBCC0\uACBD"
224
+ }
225
+ ),
226
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nexus-image-upload__format", children: formatText })
227
+ ] }),
228
+ hiddenInput
229
+ ]
230
+ }
231
+ );
232
+ const emptyView = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "nexus-image-upload__container", children: /* @__PURE__ */ jsxRuntime.jsxs(
233
+ "div",
234
+ {
235
+ role: "button",
236
+ tabIndex: disabled ? -1 : 0,
237
+ className: chunkCZC76ZD5_js.cn(
238
+ imageUploadVariants({ size }),
239
+ isDragging && "nexus-image-upload--dragging",
240
+ disabled && "nexus-image-upload--disabled",
241
+ !hasField && className
242
+ ),
243
+ onClick: handleClick,
244
+ onKeyDown: (e) => {
245
+ if (e.key === "Enter" || e.key === " ") {
246
+ e.preventDefault();
247
+ handleClick();
248
+ }
249
+ },
250
+ onDragEnter: handleDragEnter,
251
+ onDragLeave: handleDragLeave,
252
+ onDragOver: handleDragOver,
253
+ onDrop: handleDrop,
254
+ "aria-label": placeholder,
255
+ children: [
256
+ /* @__PURE__ */ jsxRuntime.jsx(ImageUpIcon, { className: "nexus-image-upload__icon" }),
257
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nexus-image-upload__text-group", children: [
258
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nexus-image-upload__text", children: placeholder }),
259
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nexus-image-upload__format", children: formatText })
260
+ ] }),
261
+ hiddenInput
262
+ ]
263
+ }
264
+ ) });
265
+ const uploadBox = preview ? previewView : emptyView;
266
+ if (!hasField) {
267
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className, children: uploadBox });
268
+ }
269
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: chunkCZC76ZD5_js.cn("nexus-image-upload-field", className), children: [
270
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nexus-image-upload-field__label", children: label }),
271
+ uploadBox,
272
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "nexus-image-upload-field__description", children: description })
273
+ ] });
274
+ }
275
+ );
276
+ ImageUpload.displayName = "ImageUpload";
277
+
278
+ exports.ImageUpload = ImageUpload;
279
+ exports.imageUploadVariants = imageUploadVariants;