@nurimedia/react-ui 0.1.0 → 0.1.2
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/dist/AlertDialog/index.cjs +4 -180
- package/dist/AlertDialog/index.cjs.map +1 -1
- package/dist/AlertDialog/index.js +5 -144
- package/dist/AlertDialog/index.js.map +1 -1
- package/dist/Button/index.cjs +4 -131
- package/dist/Button/index.cjs.map +1 -1
- package/dist/Button/index.js +5 -105
- package/dist/Button/index.js.map +1 -1
- package/dist/Checkbox/index.cjs +4 -78
- package/dist/Checkbox/index.cjs.map +1 -1
- package/dist/Checkbox/index.js +5 -42
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Input/index.cjs +4 -98
- package/dist/Input/index.cjs.map +1 -1
- package/dist/Input/index.js +5 -72
- package/dist/Input/index.js.map +1 -1
- package/dist/Modal/index.cjs +4 -115
- package/dist/Modal/index.cjs.map +1 -1
- package/dist/Modal/index.js +5 -79
- package/dist/Modal/index.js.map +1 -1
- package/dist/Radio/index.cjs +6 -81
- package/dist/Radio/index.cjs.map +1 -1
- package/dist/Radio/index.js +6 -43
- package/dist/Radio/index.js.map +1 -1
- package/dist/Select/index.cjs +4 -111
- package/dist/Select/index.cjs.map +1 -1
- package/dist/Select/index.js +5 -75
- package/dist/Select/index.js.map +1 -1
- package/dist/Switch/index.cjs +4 -66
- package/dist/Switch/index.cjs.map +1 -1
- package/dist/Switch/index.js +5 -30
- package/dist/Switch/index.js.map +1 -1
- package/dist/Textarea/index.cjs +4 -122
- package/dist/Textarea/index.cjs.map +1 -1
- package/dist/Textarea/index.js +5 -96
- package/dist/Textarea/index.js.map +1 -1
- package/dist/Toast/index.cjs +4 -177
- package/dist/Toast/index.cjs.map +1 -1
- package/dist/Toast/index.js +6 -141
- package/dist/Toast/index.js.map +1 -1
- package/dist/Tooltip/index.cjs +6 -100
- package/dist/Tooltip/index.cjs.map +1 -1
- package/dist/Tooltip/index.js +6 -62
- package/dist/Tooltip/index.js.map +1 -1
- package/dist/chunk-2LFW4MM6.cjs +47 -0
- package/dist/chunk-2LFW4MM6.cjs.map +1 -0
- package/dist/chunk-2WKLA5RC.cjs +82 -0
- package/dist/chunk-2WKLA5RC.cjs.map +1 -0
- package/dist/chunk-2YGYLCCA.js +66 -0
- package/dist/chunk-2YGYLCCA.js.map +1 -0
- package/dist/chunk-323VGYMK.cjs +147 -0
- package/dist/chunk-323VGYMK.cjs.map +1 -0
- package/dist/chunk-3H47QMKS.js +47 -0
- package/dist/chunk-3H47QMKS.js.map +1 -0
- package/dist/chunk-3QSLHLC2.cjs +45 -0
- package/dist/chunk-3QSLHLC2.cjs.map +1 -0
- package/dist/chunk-4N5JIGIU.js +82 -0
- package/dist/chunk-4N5JIGIU.js.map +1 -0
- package/dist/chunk-DTGPVOJK.js +99 -0
- package/dist/chunk-DTGPVOJK.js.map +1 -0
- package/dist/chunk-DTQE42F7.js +33 -0
- package/dist/chunk-DTQE42F7.js.map +1 -0
- package/dist/chunk-DYO4PIBB.js +75 -0
- package/dist/chunk-DYO4PIBB.js.map +1 -0
- package/dist/chunk-GBMYANHH.js +149 -0
- package/dist/chunk-GBMYANHH.js.map +1 -0
- package/dist/chunk-I7KJ7WTN.cjs +149 -0
- package/dist/chunk-I7KJ7WTN.cjs.map +1 -0
- package/dist/chunk-JM4HDCLU.cjs +110 -0
- package/dist/chunk-JM4HDCLU.cjs.map +1 -0
- package/dist/chunk-JXJ6G634.cjs +75 -0
- package/dist/chunk-JXJ6G634.cjs.map +1 -0
- package/dist/chunk-LAPTEQ5N.js +45 -0
- package/dist/chunk-LAPTEQ5N.js.map +1 -0
- package/dist/chunk-LRATCHCB.cjs +66 -0
- package/dist/chunk-LRATCHCB.cjs.map +1 -0
- package/dist/chunk-OM4QMC4F.js +110 -0
- package/dist/chunk-OM4QMC4F.js.map +1 -0
- package/dist/chunk-PAXRFQUJ.cjs +33 -0
- package/dist/chunk-PAXRFQUJ.cjs.map +1 -0
- package/dist/chunk-PC3B67B4.cjs +78 -0
- package/dist/chunk-PC3B67B4.cjs.map +1 -0
- package/dist/chunk-PS6QXS5Z.js +11 -0
- package/dist/chunk-PS6QXS5Z.js.map +1 -0
- package/dist/chunk-Q26BJSLP.cjs +99 -0
- package/dist/chunk-Q26BJSLP.cjs.map +1 -0
- package/dist/chunk-R4E4BIPC.cjs +11 -0
- package/dist/chunk-R4E4BIPC.cjs.map +1 -0
- package/dist/chunk-R757N7RU.js +78 -0
- package/dist/chunk-R757N7RU.js.map +1 -0
- package/dist/chunk-RC773ZEY.js +147 -0
- package/dist/chunk-RC773ZEY.js.map +1 -0
- package/dist/index.cjs +54 -899
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +38 -833
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkR4E4BIPCcjs = require('./chunk-R4E4BIPC.cjs');
|
|
5
|
+
|
|
6
|
+
// src/Button/Button.tsx
|
|
7
|
+
require('./Button/styles.css');
|
|
8
|
+
var _reactslot = require('@radix-ui/react-slot');
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
|
|
11
|
+
// src/Button/Spinner.tsx
|
|
12
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
13
|
+
var Spinner = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-button__icon", "aria-hidden": "true", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "nuri-button__spinner", viewBox: "0 0 16 16", width: "16", height: "16", fill: "none", children: [
|
|
14
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "circle", { cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "2" }),
|
|
15
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M14 8a6 6 0 0 0-6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
16
|
+
] }) });
|
|
17
|
+
|
|
18
|
+
// src/Button/Button.tsx
|
|
19
|
+
|
|
20
|
+
var Button = _react.forwardRef.call(void 0, function Button2({
|
|
21
|
+
variant = "primary",
|
|
22
|
+
size = "md",
|
|
23
|
+
iconLeft,
|
|
24
|
+
iconRight,
|
|
25
|
+
iconOnly = false,
|
|
26
|
+
block = false,
|
|
27
|
+
loading = false,
|
|
28
|
+
disabled = false,
|
|
29
|
+
asChild = false,
|
|
30
|
+
type = "button",
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
onClick,
|
|
34
|
+
...rest
|
|
35
|
+
}, ref) {
|
|
36
|
+
const isBlocked = disabled || loading;
|
|
37
|
+
if (process.env.NODE_ENV !== "production" && iconOnly && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
38
|
+
console.warn(
|
|
39
|
+
"[nuri/Button] `iconOnly` \uBC84\uD2BC\uC740 `aria-label`(\uB610\uB294 `aria-labelledby`)\uC774 \uD544\uC694\uD569\uB2C8\uB2E4."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const hasLeftSlot = !iconOnly && (loading || iconLeft != null);
|
|
43
|
+
const hasRightSlot = !iconOnly && !loading && iconRight != null;
|
|
44
|
+
const classes = _chunkR4E4BIPCcjs.cx.call(void 0,
|
|
45
|
+
"nuri-button",
|
|
46
|
+
`nuri-button--${variant}`,
|
|
47
|
+
`nuri-button--${size}`,
|
|
48
|
+
block && "nuri-button--block",
|
|
49
|
+
iconOnly && "nuri-button--icon-only",
|
|
50
|
+
isBlocked && "nuri-button--disabled",
|
|
51
|
+
loading && "nuri-button--loading",
|
|
52
|
+
hasLeftSlot && "nuri-button--has-left",
|
|
53
|
+
hasRightSlot && "nuri-button--has-right",
|
|
54
|
+
className
|
|
55
|
+
);
|
|
56
|
+
const handleClick = (e) => {
|
|
57
|
+
if (isBlocked) {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
_optionalChain([onClick, 'optionalCall', _ => _(e)]);
|
|
63
|
+
};
|
|
64
|
+
const renderContent = (content) => {
|
|
65
|
+
if (iconOnly) {
|
|
66
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-button__icon", "aria-hidden": "true", children: loading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, {}) : content });
|
|
67
|
+
}
|
|
68
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
69
|
+
loading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, {}) : iconLeft != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-button__icon nuri-button__icon--left", "aria-hidden": "true", children: iconLeft }),
|
|
70
|
+
content,
|
|
71
|
+
hasRightSlot && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-button__icon nuri-button__icon--right", "aria-hidden": "true", children: iconRight })
|
|
72
|
+
] });
|
|
73
|
+
};
|
|
74
|
+
if (asChild) {
|
|
75
|
+
const child = _react.Children.only(children);
|
|
76
|
+
if (!_react.isValidElement.call(void 0, child)) return null;
|
|
77
|
+
const childElement = child;
|
|
78
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
79
|
+
_reactslot.Slot,
|
|
80
|
+
{
|
|
81
|
+
ref,
|
|
82
|
+
className: classes,
|
|
83
|
+
"aria-disabled": isBlocked || void 0,
|
|
84
|
+
"aria-busy": loading || void 0,
|
|
85
|
+
onClick: handleClick,
|
|
86
|
+
...rest,
|
|
87
|
+
children: _react.cloneElement.call(void 0, childElement, void 0, renderContent(childElement.props.children))
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
92
|
+
"button",
|
|
93
|
+
{
|
|
94
|
+
ref,
|
|
95
|
+
type,
|
|
96
|
+
className: classes,
|
|
97
|
+
disabled,
|
|
98
|
+
"aria-disabled": loading || void 0,
|
|
99
|
+
"aria-busy": loading || void 0,
|
|
100
|
+
onClick: handleClick,
|
|
101
|
+
...rest,
|
|
102
|
+
children: renderContent(children)
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
exports.Button = Button;
|
|
110
|
+
//# sourceMappingURL=chunk-JM4HDCLU.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-JM4HDCLU.cjs","../src/Button/Button.tsx","../src/Button/Spinner.tsx"],"names":["Button","jsxs","jsx"],"mappings":"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","file":"/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-JM4HDCLU.cjs","sourcesContent":[null,"'use client';\n\nimport './styles.css';\nimport { Slot } from '@radix-ui/react-slot';\nimport { Children, cloneElement, forwardRef, isValidElement } from 'react';\nimport type { ButtonHTMLAttributes, MouseEvent, ReactElement, ReactNode } from 'react';\nimport { Spinner } from './Spinner.js';\nimport { cx } from '../utils/cx.js';\n\ntype Variant = 'primary' | 'secondary' | 'outline' | 'ghost';\ntype Size = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {\n /**\n * 시각 유형.\n * - `primary`: 브랜드 색 배경 (기본)\n * - `secondary`: 브랜드 옅은 톤 배경\n * - `outline`: 투명 배경 + 테두리\n * - `ghost`: 투명 배경, hover 시에만 배경 채움\n * @default 'primary'\n */\n variant?: Variant;\n\n /**\n * 사이즈.\n * - `sm`: 36px 높이 — 밀집된 UI, 테이블 액션\n * - `md`: 42px 높이 — 일반 콘텐츠 영역 (기본)\n * - `lg`: 48px 높이 — 주요 CTA, 모바일 터치\n * @default 'md'\n */\n size?: Size;\n\n /**\n * 라벨 좌측에 표시할 아이콘.\n * @example <Button iconLeft={<SearchIcon />}>검색</Button>\n */\n iconLeft?: ReactNode;\n\n /**\n * 라벨 우측에 표시할 아이콘.\n */\n iconRight?: ReactNode;\n\n /**\n * 아이콘만 표시하는 정사각 버튼. **`aria-label` 필수**\n * (icon-only는 시각적으로만 의미가 있으므로 스크린리더용 라벨이 없으면 사용자가 용도를 알 수 없음).\n * children은 단일 아이콘 엘리먼트.\n * @example <Button iconOnly aria-label=\"닫기\"><CloseIcon /></Button>\n */\n iconOnly?: boolean;\n\n /**\n * 컨테이너 전체 너비로 확장.\n */\n block?: boolean;\n\n /**\n * 로딩 중 표시. 스피너를 좌측 아이콘 자리에 표시하고, 클릭을 차단하며 `aria-busy=\"true\"`를 부여.\n */\n loading?: boolean;\n\n /**\n * Radix Slot으로 자식 엘리먼트를 렌더 — 자식이 Button의 className·ref·이벤트 핸들러를 모두 물려받음.\n * 링크를 버튼처럼 보이게 할 때 가장 자주 사용 (next/link, react-router Link 등).\n * @example\n * <Button asChild><Link href=\"/about\">소개</Link></Button>\n */\n asChild?: boolean;\n\n /**\n * 폼 버튼 타입. 의도치 않은 form submit 방지를 위해 기본값 `'button'`.\n * 폼 제출 버튼이면 명시적으로 `type=\"submit\"` 지정.\n * @default 'button'\n */\n type?: 'button' | 'submit' | 'reset';\n\n children?: ReactNode;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n variant = 'primary',\n size = 'md',\n iconLeft,\n iconRight,\n iconOnly = false,\n block = false,\n loading = false,\n disabled = false,\n asChild = false,\n type = 'button',\n className,\n children,\n onClick,\n ...rest\n },\n ref,\n) {\n const isBlocked = disabled || loading;\n\n if (\n process.env.NODE_ENV !== 'production' &&\n iconOnly &&\n !rest['aria-label'] &&\n !rest['aria-labelledby']\n ) {\n // iconOnly 버튼은 텍스트가 없어 스크린리더가 용도를 알 수 없음 → 개발 모드 경고\n console.warn(\n '[nuri/Button] `iconOnly` 버튼은 `aria-label`(또는 `aria-labelledby`)이 필요합니다.',\n );\n }\n\n const hasLeftSlot = !iconOnly && (loading || iconLeft != null);\n const hasRightSlot = !iconOnly && !loading && iconRight != null;\n\n const classes = cx(\n 'nuri-button',\n `nuri-button--${variant}`,\n `nuri-button--${size}`,\n block && 'nuri-button--block',\n iconOnly && 'nuri-button--icon-only',\n isBlocked && 'nuri-button--disabled',\n loading && 'nuri-button--loading',\n hasLeftSlot && 'nuri-button--has-left',\n hasRightSlot && 'nuri-button--has-right',\n className,\n );\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n if (isBlocked) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e);\n };\n\n const renderContent = (content: ReactNode) => {\n if (iconOnly) {\n return (\n <span className=\"nuri-button__icon\" aria-hidden=\"true\">\n {loading ? <Spinner /> : content}\n </span>\n );\n }\n return (\n <>\n {loading ? (\n <Spinner />\n ) : (\n iconLeft != null && (\n <span className=\"nuri-button__icon nuri-button__icon--left\" aria-hidden=\"true\">\n {iconLeft}\n </span>\n )\n )}\n {content}\n {hasRightSlot && (\n <span className=\"nuri-button__icon nuri-button__icon--right\" aria-hidden=\"true\">\n {iconRight}\n </span>\n )}\n </>\n );\n };\n\n if (asChild) {\n const child = Children.only(children);\n if (!isValidElement(child)) return null;\n const childElement = child as ReactElement<{ children?: ReactNode }>;\n return (\n <Slot\n ref={ref}\n className={classes}\n aria-disabled={isBlocked || undefined}\n aria-busy={loading || undefined}\n onClick={handleClick}\n {...rest}\n >\n {cloneElement(childElement, undefined, renderContent(childElement.props.children))}\n </Slot>\n );\n }\n\n return (\n <button\n ref={ref}\n type={type}\n className={classes}\n // disabled = 진짜 비활성 → native disabled (포커스 불가, 의도된 동작)\n // loading = 일시적 처리중 → aria-disabled로 포커스 유지 (클릭은 handleClick이 가드)\n disabled={disabled}\n aria-disabled={loading || undefined}\n aria-busy={loading || undefined}\n onClick={handleClick}\n {...rest}\n >\n {renderContent(children)}\n </button>\n );\n});\n","export const Spinner = () => (\n <span className=\"nuri-button__icon\" aria-hidden=\"true\">\n <svg className=\"nuri-button__spinner\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeOpacity=\"0.25\" strokeWidth=\"2\" />\n <path d=\"M14 8a6 6 0 0 0-6-6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </span>\n);\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkR4E4BIPCcjs = require('./chunk-R4E4BIPC.cjs');
|
|
5
|
+
|
|
6
|
+
// src/Input/Input.tsx
|
|
7
|
+
require('./Input/styles.css');
|
|
8
|
+
var _react = require('react');
|
|
9
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
10
|
+
var Input = _react.forwardRef.call(void 0, function Input2({
|
|
11
|
+
size = "md",
|
|
12
|
+
label,
|
|
13
|
+
hideLabel = false,
|
|
14
|
+
description,
|
|
15
|
+
invalid = false,
|
|
16
|
+
errorMessage,
|
|
17
|
+
iconLeft,
|
|
18
|
+
iconRight,
|
|
19
|
+
block = false,
|
|
20
|
+
disabled = false,
|
|
21
|
+
className,
|
|
22
|
+
id: idProp,
|
|
23
|
+
"aria-describedby": ariaDescribedby,
|
|
24
|
+
...rest
|
|
25
|
+
}, ref) {
|
|
26
|
+
const reactId = _react.useId.call(void 0, );
|
|
27
|
+
const id = _nullishCoalesce(idProp, () => ( `nuri-input-${reactId}`));
|
|
28
|
+
const messageId = `${id}-message`;
|
|
29
|
+
const message = invalid && errorMessage != null ? errorMessage : description;
|
|
30
|
+
const hasMessage = message != null;
|
|
31
|
+
const describedBy = _chunkR4E4BIPCcjs.cx.call(void 0, hasMessage ? messageId : void 0, ariaDescribedby) || void 0;
|
|
32
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkR4E4BIPCcjs.cx.call(void 0, "nuri-input", block && "nuri-input--block", className), children: [
|
|
33
|
+
label != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: id, className: _chunkR4E4BIPCcjs.cx.call(void 0, "nuri-input__label", hideLabel && "nuri-sr-only"), children: label }),
|
|
34
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
35
|
+
"div",
|
|
36
|
+
{
|
|
37
|
+
className: _chunkR4E4BIPCcjs.cx.call(void 0,
|
|
38
|
+
"nuri-input__field",
|
|
39
|
+
`nuri-input__field--${size}`,
|
|
40
|
+
invalid && "nuri-input__field--invalid",
|
|
41
|
+
disabled && "nuri-input__field--disabled"
|
|
42
|
+
),
|
|
43
|
+
children: [
|
|
44
|
+
iconLeft != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-input__icon", "aria-hidden": "true", children: iconLeft }),
|
|
45
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
46
|
+
"input",
|
|
47
|
+
{
|
|
48
|
+
ref,
|
|
49
|
+
id,
|
|
50
|
+
className: "nuri-input__control",
|
|
51
|
+
disabled,
|
|
52
|
+
"aria-invalid": invalid || void 0,
|
|
53
|
+
"aria-describedby": describedBy,
|
|
54
|
+
...rest
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
iconRight != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-input__icon", "aria-hidden": "true", children: iconRight })
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
hasMessage && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
62
|
+
"p",
|
|
63
|
+
{
|
|
64
|
+
id: messageId,
|
|
65
|
+
className: _chunkR4E4BIPCcjs.cx.call(void 0, "nuri-input__message", invalid && "nuri-input__message--error"),
|
|
66
|
+
children: message
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
exports.Input = Input;
|
|
75
|
+
//# sourceMappingURL=chunk-JXJ6G634.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-JXJ6G634.cjs","../src/Input/Input.tsx"],"names":["Input"],"mappings":"AAAA,yLAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACA;ACHA,8BAAO;AACP,8BAAkC;AAqF1B,+CAAA;AAhCD,IAAM,MAAA,EAAQ,+BAAA,SAAkDA,MAAAA,CACrE;AAAA,EACE,KAAA,EAAO,IAAA;AAAA,EACP,KAAA;AAAA,EACA,UAAA,EAAY,KAAA;AAAA,EACZ,WAAA;AAAA,EACA,QAAA,EAAU,KAAA;AAAA,EACV,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA,EAAQ,KAAA;AAAA,EACR,SAAA,EAAW,KAAA;AAAA,EACX,SAAA;AAAA,EACA,EAAA,EAAI,MAAA;AAAA,EACJ,kBAAA,EAAoB,eAAA;AAAA,EACpB,GAAG;AACL,CAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,QAAA,EAAU,0BAAA,CAAM;AACtB,EAAA,MAAM,GAAA,mBAAK,MAAA,UAAU,CAAA,WAAA,EAAc,OAAO,CAAA,GAAA;AACnB,EAAA;AAGoB,EAAA;AACb,EAAA;AAEZ,EAAA;AAGX,EAAA;AAEA,IAAA;AAKH,oBAAA;AAAC,MAAA;AAAA,MAAA;AACY,QAAA;AACT,UAAA;AAC0B,UAAA;AACf,UAAA;AACC,UAAA;AACd,QAAA;AAEC,QAAA;AACC,UAAA;AAIF,0BAAA;AAAC,YAAA;AAAA,YAAA;AACC,cAAA;AACA,cAAA;AACU,cAAA;AACV,cAAA;AACyB,cAAA;AACP,cAAA;AACd,cAAA;AAAA,YAAA;AACN,UAAA;AAEE,UAAA;AAEA,QAAA;AAAA,MAAA;AAEJ,IAAA;AAGE,IAAA;AAAC,MAAA;AAAA,MAAA;AACK,QAAA;AACiC,QAAA;AAEpC,QAAA;AAAA,MAAA;AACH,IAAA;AAEJ,EAAA;AAEH;AD9D4C;AACA;AACA;AACA","file":"/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-JXJ6G634.cjs","sourcesContent":[null,"'use client';\n\nimport './styles.css';\nimport { forwardRef, useId } from 'react';\nimport type { InputHTMLAttributes, ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\ntype Size = 'sm' | 'md' | 'lg';\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {\n /**\n * 사이즈. sm 36 / md 42 / lg 48 px 높이.\n * @default 'md'\n */\n size?: Size;\n /**\n * 라벨 (필드 위). 지정 시 `<label>`로 렌더되어 자동 연결됨.\n * 라벨을 두지 않으면 `aria-label`로 접근 가능한 이름을 주세요\n * (placeholder는 이름을 대체하지 못함 — 입력 시 사라지고 대비가 낮음).\n */\n label?: ReactNode;\n /**\n * 라벨을 시각적으로만 숨김 (스크린리더에는 노출). 디자인상 라벨을 안 보이게 하되\n * 접근성 이름은 유지할 때 사용.\n * @default false\n */\n hideLabel?: boolean;\n /** 평상시 힌트 (회색, 필드 아래). `aria-describedby`로 연결됨. */\n description?: ReactNode;\n /** 에러 상태 — 보더·텍스트·배경이 에러색으로 바뀌고 `aria-invalid`가 설정됨. */\n invalid?: boolean;\n /** `invalid`일 때 표시할 에러 메시지 (빨강). 있으면 description을 대체. */\n errorMessage?: ReactNode;\n /** 좌측 어도먼트 (아이콘 등). */\n iconLeft?: ReactNode;\n /** 우측 어도먼트 (아이콘·clear·버튼 등). */\n iconRight?: ReactNode;\n /** 컨테이너 전체 너비로 확장. @default false */\n block?: boolean;\n}\n\n/**\n * 텍스트 입력 필드. 옵션으로 라벨(위)·헬퍼/에러 메시지(아래)를 포함하는 자체 완결형.\n * 상태(default/focus/invalid/disabled)는 CSS로, 값 채움(filled)은 네이티브로 처리.\n *\n * @example 기본\n * <Input placeholder=\"검색어\" aria-label=\"검색\" />\n *\n * @example 라벨 + 헬퍼 + 에러\n * <Input\n * label=\"비밀번호\"\n * description=\"8자 이상 입력하세요\"\n * invalid\n * errorMessage=\"비밀번호가 일치하지 않습니다\"\n * />\n */\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(\n {\n size = 'md',\n label,\n hideLabel = false,\n description,\n invalid = false,\n errorMessage,\n iconLeft,\n iconRight,\n block = false,\n disabled = false,\n className,\n id: idProp,\n 'aria-describedby': ariaDescribedby,\n ...rest\n },\n ref,\n) {\n const reactId = useId();\n const id = idProp ?? `nuri-input-${reactId}`;\n const messageId = `${id}-message`;\n\n // invalid + errorMessage → 에러 메시지 / 아니면 힌트. 시각 슬롯은 항상 한 줄.\n const message = invalid && errorMessage != null ? errorMessage : description;\n const hasMessage = message != null;\n const describedBy =\n cx(hasMessage ? messageId : undefined, ariaDescribedby as string | undefined) || undefined;\n\n return (\n <div className={cx('nuri-input', block && 'nuri-input--block', className)}>\n {label != null && (\n <label htmlFor={id} className={cx('nuri-input__label', hideLabel && 'nuri-sr-only')}>\n {label}\n </label>\n )}\n\n <div\n className={cx(\n 'nuri-input__field',\n `nuri-input__field--${size}`,\n invalid && 'nuri-input__field--invalid',\n disabled && 'nuri-input__field--disabled',\n )}\n >\n {iconLeft != null && (\n <span className=\"nuri-input__icon\" aria-hidden=\"true\">\n {iconLeft}\n </span>\n )}\n <input\n ref={ref}\n id={id}\n className=\"nuri-input__control\"\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n {...rest}\n />\n {iconRight != null && (\n <span className=\"nuri-input__icon\" aria-hidden=\"true\">\n {iconRight}\n </span>\n )}\n </div>\n\n {hasMessage && (\n <p\n id={messageId}\n className={cx('nuri-input__message', invalid && 'nuri-input__message--error')}\n >\n {message}\n </p>\n )}\n </div>\n );\n});\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
cx
|
|
4
|
+
} from "./chunk-PS6QXS5Z.js";
|
|
5
|
+
|
|
6
|
+
// src/Checkbox/Checkbox.tsx
|
|
7
|
+
import "./Checkbox/styles.css";
|
|
8
|
+
import * as RadixCheckbox from "@radix-ui/react-checkbox";
|
|
9
|
+
import { forwardRef, useId } from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
var CheckIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
12
|
+
"path",
|
|
13
|
+
{
|
|
14
|
+
d: "M2.5 6.2l2.4 2.4 4.6-5",
|
|
15
|
+
stroke: "currentColor",
|
|
16
|
+
strokeWidth: "1.6",
|
|
17
|
+
strokeLinecap: "round",
|
|
18
|
+
strokeLinejoin: "round"
|
|
19
|
+
}
|
|
20
|
+
) });
|
|
21
|
+
var IndeterminateIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M2.8 6h6.4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }) });
|
|
22
|
+
var Checkbox = forwardRef(function Checkbox2({ label, size = "md", disabled = false, id: idProp, className, checked, ...rest }, ref) {
|
|
23
|
+
const reactId = useId();
|
|
24
|
+
const id = idProp ?? `nuri-checkbox-${reactId}`;
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("nuri-checkbox", `nuri-checkbox--${size}`, className), children: [
|
|
26
|
+
/* @__PURE__ */ jsx(
|
|
27
|
+
RadixCheckbox.Root,
|
|
28
|
+
{
|
|
29
|
+
ref,
|
|
30
|
+
id,
|
|
31
|
+
className: "nuri-checkbox__control",
|
|
32
|
+
disabled,
|
|
33
|
+
checked,
|
|
34
|
+
...rest,
|
|
35
|
+
children: /* @__PURE__ */ jsx(RadixCheckbox.Indicator, { className: "nuri-checkbox__indicator", children: checked === "indeterminate" ? /* @__PURE__ */ jsx(IndeterminateIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
label != null && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "nuri-checkbox__label", children: label })
|
|
39
|
+
] });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
Checkbox
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=chunk-LAPTEQ5N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Checkbox/Checkbox.tsx"],"sourcesContent":["'use client';\n\nimport './styles.css';\nimport * as RadixCheckbox from '@radix-ui/react-checkbox';\nimport { forwardRef, useId } from 'react';\nimport type { ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\ntype Size = 'sm' | 'md';\n\nexport interface CheckboxProps {\n /** 라벨 (컨트롤 우측). 지정 시 클릭 영역에 포함되고 자동 연결됨. 없으면 `aria-label` 필수. */\n label?: ReactNode;\n /**\n * 사이즈. md 16px(디자인 Large, 기본) / sm 12px(디자인 Small).\n * @default 'md'\n */\n size?: Size;\n /** 체크 상태 (제어형). `'indeterminate'`는 부분 선택 표시. */\n checked?: boolean | 'indeterminate';\n /** 초기 체크 상태 (비제어형). */\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean | 'indeterminate') => void;\n disabled?: boolean;\n /** 폼 전송용 name — 네이티브 checkbox처럼 폼에 참여. */\n name?: string;\n /** 폼 전송 시 값. @default 'on' */\n value?: string;\n required?: boolean;\n id?: string;\n className?: string;\n 'aria-label'?: string;\n}\n\n/** 체크마크. TODO(Figma 실측): 디자이너 아이콘으로 교체 예정 — 잠정 표준형. */\nconst CheckIcon = () => (\n <svg viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M2.5 6.2l2.4 2.4 4.6-5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n/** 부분 선택(indeterminate) 표시 — 가로 막대. */\nconst IndeterminateIcon = () => (\n <svg viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M2.8 6h6.4\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n);\n\n/**\n * 체크박스. Radix Checkbox 기반 — Space 토글·aria-checked·폼 참여 자동.\n * 라벨을 지정하면 라벨 클릭으로도 토글된다.\n *\n * @example\n * <Checkbox label=\"이용약관에 동의합니다\" checked={agreed} onCheckedChange={setAgreed} />\n *\n * @example 부분 선택 (전체선택 헤더 등)\n * <Checkbox label=\"전체 선택\" checked={someChecked ? 'indeterminate' : allChecked} … />\n */\nexport const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(function Checkbox(\n { label, size = 'md', disabled = false, id: idProp, className, checked, ...rest },\n ref,\n) {\n const reactId = useId();\n const id = idProp ?? `nuri-checkbox-${reactId}`;\n\n return (\n <div className={cx('nuri-checkbox', `nuri-checkbox--${size}`, className)}>\n <RadixCheckbox.Root\n ref={ref}\n id={id}\n className=\"nuri-checkbox__control\"\n disabled={disabled}\n checked={checked}\n {...rest}\n >\n <RadixCheckbox.Indicator className=\"nuri-checkbox__indicator\">\n {checked === 'indeterminate' ? <IndeterminateIcon /> : <CheckIcon />}\n </RadixCheckbox.Indicator>\n </RadixCheckbox.Root>\n {label != null && (\n <label htmlFor={id} className=\"nuri-checkbox__label\">\n {label}\n </label>\n )}\n </div>\n );\n});\n"],"mappings":";;;;;;AAEA,OAAO;AACP,YAAY,mBAAmB;AAC/B,SAAS,YAAY,aAAa;AAiC9B,cAmCA,YAnCA;AAFJ,IAAM,YAAY,MAChB,oBAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,eAAY,QAC/C;AAAA,EAAC;AAAA;AAAA,IACC,GAAE;AAAA,IACF,QAAO;AAAA,IACP,aAAY;AAAA,IACZ,eAAc;AAAA,IACd,gBAAe;AAAA;AACjB,GACF;AAIF,IAAM,oBAAoB,MACxB,oBAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,eAAY,QAC/C,8BAAC,UAAK,GAAE,cAAa,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,GACrF;AAaK,IAAM,WAAW,WAA6C,SAASA,UAC5E,EAAE,OAAO,OAAO,MAAM,WAAW,OAAO,IAAI,QAAQ,WAAW,SAAS,GAAG,KAAK,GAChF,KACA;AACA,QAAM,UAAU,MAAM;AACtB,QAAM,KAAK,UAAU,iBAAiB,OAAO;AAE7C,SACE,qBAAC,SAAI,WAAW,GAAG,iBAAiB,kBAAkB,IAAI,IAAI,SAAS,GACrE;AAAA;AAAA,MAAe;AAAA,MAAd;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAU;AAAA,QACV;AAAA,QACA;AAAA,QACC,GAAG;AAAA,QAEJ,8BAAe,yBAAd,EAAwB,WAAU,4BAChC,sBAAY,kBAAkB,oBAAC,qBAAkB,IAAK,oBAAC,aAAU,GACpE;AAAA;AAAA,IACF;AAAA,IACC,SAAS,QACR,oBAAC,WAAM,SAAS,IAAI,WAAU,wBAC3B,iBACH;AAAA,KAEJ;AAEJ,CAAC;","names":["Checkbox"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkR4E4BIPCcjs = require('./chunk-R4E4BIPC.cjs');
|
|
5
|
+
|
|
6
|
+
// src/Tooltip/Tooltip.tsx
|
|
7
|
+
require('./Tooltip/styles.css');
|
|
8
|
+
var _reacttooltip = require('@radix-ui/react-tooltip'); var RadixTooltip = _interopRequireWildcard(_reacttooltip);
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
11
|
+
var HasProviderContext = _react.createContext.call(void 0, false);
|
|
12
|
+
function TooltipProvider({ children, ...props }) {
|
|
13
|
+
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HasProviderContext.Provider, { value: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixTooltip.Provider, { ...props, children }) });
|
|
14
|
+
}
|
|
15
|
+
function Tooltip({
|
|
16
|
+
content,
|
|
17
|
+
children,
|
|
18
|
+
side = "top",
|
|
19
|
+
align = "center",
|
|
20
|
+
arrow = true,
|
|
21
|
+
delayDuration,
|
|
22
|
+
open,
|
|
23
|
+
defaultOpen,
|
|
24
|
+
onOpenChange,
|
|
25
|
+
disabled = false,
|
|
26
|
+
container,
|
|
27
|
+
className
|
|
28
|
+
}) {
|
|
29
|
+
const hasProvider = _react.useContext.call(void 0, HasProviderContext);
|
|
30
|
+
if (disabled) return children;
|
|
31
|
+
const root = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
32
|
+
RadixTooltip.Root,
|
|
33
|
+
{
|
|
34
|
+
open,
|
|
35
|
+
defaultOpen,
|
|
36
|
+
onOpenChange,
|
|
37
|
+
delayDuration,
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixTooltip.Trigger, { asChild: true, children }),
|
|
40
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixTooltip.Portal, { container, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
41
|
+
RadixTooltip.Content,
|
|
42
|
+
{
|
|
43
|
+
className: _chunkR4E4BIPCcjs.cx.call(void 0, "nuri-tooltip", className),
|
|
44
|
+
side,
|
|
45
|
+
align,
|
|
46
|
+
sideOffset: 4,
|
|
47
|
+
collisionPadding: 8,
|
|
48
|
+
arrowPadding: 6,
|
|
49
|
+
hideWhenDetached: true,
|
|
50
|
+
children: [
|
|
51
|
+
content,
|
|
52
|
+
arrow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixTooltip.Arrow, { className: "nuri-tooltip__arrow", width: 14, height: 7 })
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
) })
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
return hasProvider ? root : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixTooltip.Provider, { delayDuration: 100, children: root });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
exports.TooltipProvider = TooltipProvider; exports.Tooltip = Tooltip;
|
|
66
|
+
//# sourceMappingURL=chunk-LRATCHCB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-LRATCHCB.cjs","../src/Tooltip/Tooltip.tsx"],"names":[],"mappings":"AAAA,uWAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACA;ACHA,gCAAO;AACP,kHAA8B;AAC9B,8BAA0C;AAyDpC,+CAAA;AAfN,IAAM,mBAAA,EAAqB,kCAAA,KAAmB,CAAA;AAYvC,SAAS,eAAA,CAAgB,EAAE,QAAA,EAAU,GAAG,MAAM,CAAA,EAAyB;AAC5E,EAAA,uBACE,6BAAA,kBAAC,CAAmB,QAAA,EAAnB,EAA4B,KAAA,EAAO,IAAA,EAClC,QAAA,kBAAA,6BAAA,YAAc,CAAA,QAAA,EAAb,EAAuB,GAAG,KAAA,EAAQ,SAAA,CAAS,EAAA,CAC9C,CAAA;AAEJ;AAeO,SAAS,OAAA,CAAQ;AAAA,EACtB,OAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,IAAA;AAAA,EACR,aAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA,EAAW,KAAA;AAAA,EACX,SAAA;AAAA,EACA;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,YAAA,EAAc,+BAAA,kBAA6B,CAAA;AAEjD,EAAA,GAAA,CAAI,QAAA,EAAU,OAAO,QAAA;AAErB,EAAA,MAAM,KAAA,kBACJ,8BAAA;AAAA,IAAc,YAAA,CAAA,IAAA;AAAA,IAAb;AAAA,MACC,IAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,6BAAA,YAAc,CAAA,OAAA,EAAb,EAAqB,OAAA,EAAO,IAAA,EAAE,SAAA,CAAS,CAAA;AAAA,wBACxC,6BAAA,YAAc,CAAA,MAAA,EAAb,EAAoB,SAAA,EACnB,QAAA,kBAAA,8BAAA;AAAA,UAAc,YAAA,CAAA,OAAA;AAAA,UAAb;AAAA,YACC,SAAA,EAAW,kCAAA,cAAG,EAAgB,SAAS,CAAA;AAAA,YACvC,IAAA;AAAA,YACA,KAAA;AAAA,YACA,UAAA,EAAY,CAAA;AAAA,YACZ,gBAAA,EAAkB,CAAA;AAAA,YAClB,YAAA,EAAc,CAAA;AAAA,YAGd,gBAAA,EAAgB,IAAA;AAAA,YAEf,QAAA,EAAA;AAAA,cAAA,OAAA;AAAA,cACA,MAAA,mBAAS,6BAAA,YAAc,CAAA,KAAA,EAAb,EAAmB,SAAA,EAAU,qBAAA,EAAsB,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,EAAA,CAAG;AAAA,YAAA;AAAA,UAAA;AAAA,QACtF,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,CAAA;AAQF,EAAA,OAAO,YAAA,EACL,KAAA,kBAEA,6BAAA,YAAc,CAAA,QAAA,EAAb,EAAsB,aAAA,EAAe,GAAA,EAAM,QAAA,EAAA,KAAA,CAAK,CAAA;AAErD;AD1EA;AACA;AACE;AACA;AACF,qEAAC","file":"/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-LRATCHCB.cjs","sourcesContent":[null,"'use client';\n\nimport './styles.css';\nimport * as RadixTooltip from '@radix-ui/react-tooltip';\nimport { createContext, useContext } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\ntype Align = 'start' | 'center' | 'end';\n\nexport interface TooltipProps {\n /** 툴팁 내용. */\n content: ReactNode;\n /** 트리거 — 단일 엘리먼트에 asChild로 위임 (Button, 아이콘 버튼 등). */\n children: ReactElement;\n /**\n * 툴팁이 뜨는 방향. (디자인의 Direction은 꼬리 방향 기준이라 반대 —\n * 예: 디자인 Direction=Bottom ⇒ side=\"top\")\n * 공간이 부족하면 자동으로 반대쪽으로 반전된다.\n * @default 'top'\n */\n side?: Side;\n /** 트리거 기준 정렬. @default 'center' */\n align?: Align;\n /** 꼬리(화살표) 표시 여부 — 디자인의 showTail. @default true */\n arrow?: boolean;\n /**\n * 열림 지연 ms. 미지정 시 — 단독 사용은 100ms(거의 즉시, 스쳐 지나갈 때 깜빡임만 방지),\n * TooltipProvider 안에서는 프로바이더 설정을 따름. 0이면 즉시.\n * 키보드 포커스는 지연 없이 항상 즉시 표시된다.\n */\n delayDuration?: number;\n /** 열림 상태 제어 — 항상 표시(코치마크류)나 수동 제어에 사용. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** true면 툴팁 없이 트리거만 렌더 (조건부 툴팁). @default false */\n disabled?: boolean;\n /** 포털 렌더 대상. 기본 document.body. */\n container?: HTMLElement | null;\n /** 툴팁 패널에 추가할 className. */\n className?: string;\n}\n\n// TooltipProvider 존재 감지용 — 없으면 Tooltip이 자체 Provider로 감싼다(제로 셋업).\nconst HasProviderContext = createContext(false);\n\nexport type TooltipProviderProps = RadixTooltip.TooltipProviderProps;\n\n/**\n * 지연 시간을 공유하는 프로바이더 (선택). 앱 루트에 1회 두면 툴팁 하나를 본 직후\n * 인접 트리거로 이동할 때 지연 없이 바로 표시된다(skipDelayDuration).\n * 없어도 Tooltip은 단독으로 동작한다.\n *\n * @example\n * <TooltipProvider delayDuration={300}><App /></TooltipProvider>\n */\nexport function TooltipProvider({ children, ...props }: TooltipProviderProps) {\n return (\n <HasProviderContext.Provider value={true}>\n <RadixTooltip.Provider {...props}>{children}</RadixTooltip.Provider>\n </HasProviderContext.Provider>\n );\n}\n\n/**\n * 툴팁. Radix Tooltip 기반 — hover와 **키보드 포커스** 모두에서 열리고,\n * Esc로 닫히며, `aria-describedby`가 자동 연결된다. 포털 + 충돌 감지\n * 포지셔닝이라 부모 overflow에 잘리지 않고 화면 밖으로 나가지 않는다.\n *\n * 터치 기기에서는 표시되지 않는다(hover 개념 부재 — Radix 기본 동작).\n * 닫기 버튼이 있는 지속형 안내(코치마크)는 툴팁 범위가 아니다.\n *\n * @example\n * <Tooltip content=\"즐겨찾기에 추가\">\n * <Button iconOnly aria-label=\"즐겨찾기\">★</Button>\n * </Tooltip>\n */\nexport function Tooltip({\n content,\n children,\n side = 'top',\n align = 'center',\n arrow = true,\n delayDuration,\n open,\n defaultOpen,\n onOpenChange,\n disabled = false,\n container,\n className,\n}: TooltipProps) {\n const hasProvider = useContext(HasProviderContext);\n\n if (disabled) return children;\n\n const root = (\n <RadixTooltip.Root\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n delayDuration={delayDuration}\n >\n <RadixTooltip.Trigger asChild>{children}</RadixTooltip.Trigger>\n <RadixTooltip.Portal container={container}>\n <RadixTooltip.Content\n className={cx('nuri-tooltip', className)}\n side={side}\n align={align}\n sideOffset={4}\n collisionPadding={8}\n arrowPadding={6}\n // 트리거가 뷰포트/스크롤 영역에서 완전히 사라지면 툴팁도 숨김\n // (기준 요소 없이 툴팁만 떠 있는 현상 방지)\n hideWhenDetached\n >\n {content}\n {arrow && <RadixTooltip.Arrow className=\"nuri-tooltip__arrow\" width={14} height={7} />}\n </RadixTooltip.Content>\n </RadixTooltip.Portal>\n </RadixTooltip.Root>\n );\n\n // 앱에 TooltipProvider가 없어도 동작하도록 자체 Provider로 폴백.\n // 앱 Provider가 있으면 감싸지 않는다 — 안쪽 컨텍스트가 이기므로 여기서 또 감싸면\n // 앱이 설정한 delayDuration·skipDelayDuration이 무시된다.\n // 폴백 지연 100ms — 거의 즉시로 느껴지되, 마우스가 스쳐 지나갈 때 연쇄 깜빡임은 방지\n // (버튼 하나를 가로지르는 데 ~30–50ms — 그보다 길게 머문 경우만 의도로 판정).\n return hasProvider ? (\n root\n ) : (\n <RadixTooltip.Provider delayDuration={100}>{root}</RadixTooltip.Provider>\n );\n}\n"]}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
cx
|
|
4
|
+
} from "./chunk-PS6QXS5Z.js";
|
|
5
|
+
|
|
6
|
+
// src/Button/Button.tsx
|
|
7
|
+
import "./Button/styles.css";
|
|
8
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
9
|
+
import { Children, cloneElement, forwardRef, isValidElement } from "react";
|
|
10
|
+
|
|
11
|
+
// src/Button/Spinner.tsx
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var Spinner = () => /* @__PURE__ */ jsx("span", { className: "nuri-button__icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxs("svg", { className: "nuri-button__spinner", viewBox: "0 0 16 16", width: "16", height: "16", fill: "none", children: [
|
|
14
|
+
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "2" }),
|
|
15
|
+
/* @__PURE__ */ jsx("path", { d: "M14 8a6 6 0 0 0-6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
16
|
+
] }) });
|
|
17
|
+
|
|
18
|
+
// src/Button/Button.tsx
|
|
19
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
20
|
+
var Button = forwardRef(function Button2({
|
|
21
|
+
variant = "primary",
|
|
22
|
+
size = "md",
|
|
23
|
+
iconLeft,
|
|
24
|
+
iconRight,
|
|
25
|
+
iconOnly = false,
|
|
26
|
+
block = false,
|
|
27
|
+
loading = false,
|
|
28
|
+
disabled = false,
|
|
29
|
+
asChild = false,
|
|
30
|
+
type = "button",
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
onClick,
|
|
34
|
+
...rest
|
|
35
|
+
}, ref) {
|
|
36
|
+
const isBlocked = disabled || loading;
|
|
37
|
+
if (process.env.NODE_ENV !== "production" && iconOnly && !rest["aria-label"] && !rest["aria-labelledby"]) {
|
|
38
|
+
console.warn(
|
|
39
|
+
"[nuri/Button] `iconOnly` \uBC84\uD2BC\uC740 `aria-label`(\uB610\uB294 `aria-labelledby`)\uC774 \uD544\uC694\uD569\uB2C8\uB2E4."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
const hasLeftSlot = !iconOnly && (loading || iconLeft != null);
|
|
43
|
+
const hasRightSlot = !iconOnly && !loading && iconRight != null;
|
|
44
|
+
const classes = cx(
|
|
45
|
+
"nuri-button",
|
|
46
|
+
`nuri-button--${variant}`,
|
|
47
|
+
`nuri-button--${size}`,
|
|
48
|
+
block && "nuri-button--block",
|
|
49
|
+
iconOnly && "nuri-button--icon-only",
|
|
50
|
+
isBlocked && "nuri-button--disabled",
|
|
51
|
+
loading && "nuri-button--loading",
|
|
52
|
+
hasLeftSlot && "nuri-button--has-left",
|
|
53
|
+
hasRightSlot && "nuri-button--has-right",
|
|
54
|
+
className
|
|
55
|
+
);
|
|
56
|
+
const handleClick = (e) => {
|
|
57
|
+
if (isBlocked) {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
e.stopPropagation();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
onClick?.(e);
|
|
63
|
+
};
|
|
64
|
+
const renderContent = (content) => {
|
|
65
|
+
if (iconOnly) {
|
|
66
|
+
return /* @__PURE__ */ jsx2("span", { className: "nuri-button__icon", "aria-hidden": "true", children: loading ? /* @__PURE__ */ jsx2(Spinner, {}) : content });
|
|
67
|
+
}
|
|
68
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
69
|
+
loading ? /* @__PURE__ */ jsx2(Spinner, {}) : iconLeft != null && /* @__PURE__ */ jsx2("span", { className: "nuri-button__icon nuri-button__icon--left", "aria-hidden": "true", children: iconLeft }),
|
|
70
|
+
content,
|
|
71
|
+
hasRightSlot && /* @__PURE__ */ jsx2("span", { className: "nuri-button__icon nuri-button__icon--right", "aria-hidden": "true", children: iconRight })
|
|
72
|
+
] });
|
|
73
|
+
};
|
|
74
|
+
if (asChild) {
|
|
75
|
+
const child = Children.only(children);
|
|
76
|
+
if (!isValidElement(child)) return null;
|
|
77
|
+
const childElement = child;
|
|
78
|
+
return /* @__PURE__ */ jsx2(
|
|
79
|
+
Slot,
|
|
80
|
+
{
|
|
81
|
+
ref,
|
|
82
|
+
className: classes,
|
|
83
|
+
"aria-disabled": isBlocked || void 0,
|
|
84
|
+
"aria-busy": loading || void 0,
|
|
85
|
+
onClick: handleClick,
|
|
86
|
+
...rest,
|
|
87
|
+
children: cloneElement(childElement, void 0, renderContent(childElement.props.children))
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
return /* @__PURE__ */ jsx2(
|
|
92
|
+
"button",
|
|
93
|
+
{
|
|
94
|
+
ref,
|
|
95
|
+
type,
|
|
96
|
+
className: classes,
|
|
97
|
+
disabled,
|
|
98
|
+
"aria-disabled": loading || void 0,
|
|
99
|
+
"aria-busy": loading || void 0,
|
|
100
|
+
onClick: handleClick,
|
|
101
|
+
...rest,
|
|
102
|
+
children: renderContent(children)
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
Button
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=chunk-OM4QMC4F.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Button/Button.tsx","../src/Button/Spinner.tsx"],"sourcesContent":["'use client';\n\nimport './styles.css';\nimport { Slot } from '@radix-ui/react-slot';\nimport { Children, cloneElement, forwardRef, isValidElement } from 'react';\nimport type { ButtonHTMLAttributes, MouseEvent, ReactElement, ReactNode } from 'react';\nimport { Spinner } from './Spinner.js';\nimport { cx } from '../utils/cx.js';\n\ntype Variant = 'primary' | 'secondary' | 'outline' | 'ghost';\ntype Size = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> {\n /**\n * 시각 유형.\n * - `primary`: 브랜드 색 배경 (기본)\n * - `secondary`: 브랜드 옅은 톤 배경\n * - `outline`: 투명 배경 + 테두리\n * - `ghost`: 투명 배경, hover 시에만 배경 채움\n * @default 'primary'\n */\n variant?: Variant;\n\n /**\n * 사이즈.\n * - `sm`: 36px 높이 — 밀집된 UI, 테이블 액션\n * - `md`: 42px 높이 — 일반 콘텐츠 영역 (기본)\n * - `lg`: 48px 높이 — 주요 CTA, 모바일 터치\n * @default 'md'\n */\n size?: Size;\n\n /**\n * 라벨 좌측에 표시할 아이콘.\n * @example <Button iconLeft={<SearchIcon />}>검색</Button>\n */\n iconLeft?: ReactNode;\n\n /**\n * 라벨 우측에 표시할 아이콘.\n */\n iconRight?: ReactNode;\n\n /**\n * 아이콘만 표시하는 정사각 버튼. **`aria-label` 필수**\n * (icon-only는 시각적으로만 의미가 있으므로 스크린리더용 라벨이 없으면 사용자가 용도를 알 수 없음).\n * children은 단일 아이콘 엘리먼트.\n * @example <Button iconOnly aria-label=\"닫기\"><CloseIcon /></Button>\n */\n iconOnly?: boolean;\n\n /**\n * 컨테이너 전체 너비로 확장.\n */\n block?: boolean;\n\n /**\n * 로딩 중 표시. 스피너를 좌측 아이콘 자리에 표시하고, 클릭을 차단하며 `aria-busy=\"true\"`를 부여.\n */\n loading?: boolean;\n\n /**\n * Radix Slot으로 자식 엘리먼트를 렌더 — 자식이 Button의 className·ref·이벤트 핸들러를 모두 물려받음.\n * 링크를 버튼처럼 보이게 할 때 가장 자주 사용 (next/link, react-router Link 등).\n * @example\n * <Button asChild><Link href=\"/about\">소개</Link></Button>\n */\n asChild?: boolean;\n\n /**\n * 폼 버튼 타입. 의도치 않은 form submit 방지를 위해 기본값 `'button'`.\n * 폼 제출 버튼이면 명시적으로 `type=\"submit\"` 지정.\n * @default 'button'\n */\n type?: 'button' | 'submit' | 'reset';\n\n children?: ReactNode;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(\n {\n variant = 'primary',\n size = 'md',\n iconLeft,\n iconRight,\n iconOnly = false,\n block = false,\n loading = false,\n disabled = false,\n asChild = false,\n type = 'button',\n className,\n children,\n onClick,\n ...rest\n },\n ref,\n) {\n const isBlocked = disabled || loading;\n\n if (\n process.env.NODE_ENV !== 'production' &&\n iconOnly &&\n !rest['aria-label'] &&\n !rest['aria-labelledby']\n ) {\n // iconOnly 버튼은 텍스트가 없어 스크린리더가 용도를 알 수 없음 → 개발 모드 경고\n console.warn(\n '[nuri/Button] `iconOnly` 버튼은 `aria-label`(또는 `aria-labelledby`)이 필요합니다.',\n );\n }\n\n const hasLeftSlot = !iconOnly && (loading || iconLeft != null);\n const hasRightSlot = !iconOnly && !loading && iconRight != null;\n\n const classes = cx(\n 'nuri-button',\n `nuri-button--${variant}`,\n `nuri-button--${size}`,\n block && 'nuri-button--block',\n iconOnly && 'nuri-button--icon-only',\n isBlocked && 'nuri-button--disabled',\n loading && 'nuri-button--loading',\n hasLeftSlot && 'nuri-button--has-left',\n hasRightSlot && 'nuri-button--has-right',\n className,\n );\n\n const handleClick = (e: MouseEvent<HTMLButtonElement>) => {\n if (isBlocked) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n onClick?.(e);\n };\n\n const renderContent = (content: ReactNode) => {\n if (iconOnly) {\n return (\n <span className=\"nuri-button__icon\" aria-hidden=\"true\">\n {loading ? <Spinner /> : content}\n </span>\n );\n }\n return (\n <>\n {loading ? (\n <Spinner />\n ) : (\n iconLeft != null && (\n <span className=\"nuri-button__icon nuri-button__icon--left\" aria-hidden=\"true\">\n {iconLeft}\n </span>\n )\n )}\n {content}\n {hasRightSlot && (\n <span className=\"nuri-button__icon nuri-button__icon--right\" aria-hidden=\"true\">\n {iconRight}\n </span>\n )}\n </>\n );\n };\n\n if (asChild) {\n const child = Children.only(children);\n if (!isValidElement(child)) return null;\n const childElement = child as ReactElement<{ children?: ReactNode }>;\n return (\n <Slot\n ref={ref}\n className={classes}\n aria-disabled={isBlocked || undefined}\n aria-busy={loading || undefined}\n onClick={handleClick}\n {...rest}\n >\n {cloneElement(childElement, undefined, renderContent(childElement.props.children))}\n </Slot>\n );\n }\n\n return (\n <button\n ref={ref}\n type={type}\n className={classes}\n // disabled = 진짜 비활성 → native disabled (포커스 불가, 의도된 동작)\n // loading = 일시적 처리중 → aria-disabled로 포커스 유지 (클릭은 handleClick이 가드)\n disabled={disabled}\n aria-disabled={loading || undefined}\n aria-busy={loading || undefined}\n onClick={handleClick}\n {...rest}\n >\n {renderContent(children)}\n </button>\n );\n});\n","export const Spinner = () => (\n <span className=\"nuri-button__icon\" aria-hidden=\"true\">\n <svg className=\"nuri-button__spinner\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" strokeOpacity=\"0.25\" strokeWidth=\"2\" />\n <path d=\"M14 8a6 6 0 0 0-6-6\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </span>\n);\n"],"mappings":"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","names":["jsx","jsxs","Button"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkR4E4BIPCcjs = require('./chunk-R4E4BIPC.cjs');
|
|
5
|
+
|
|
6
|
+
// src/Switch/Switch.tsx
|
|
7
|
+
require('./Switch/styles.css');
|
|
8
|
+
var _reactswitch = require('@radix-ui/react-switch'); var RadixSwitch = _interopRequireWildcard(_reactswitch);
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
11
|
+
var Switch = _react.forwardRef.call(void 0, function Switch2({ label, disabled = false, id: idProp, className, ...rest }, ref) {
|
|
12
|
+
const reactId = _react.useId.call(void 0, );
|
|
13
|
+
const id = _nullishCoalesce(idProp, () => ( `nuri-switch-${reactId}`));
|
|
14
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkR4E4BIPCcjs.cx.call(void 0, "nuri-switch", className), children: [
|
|
15
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
16
|
+
RadixSwitch.Root,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
id,
|
|
20
|
+
className: "nuri-switch__control",
|
|
21
|
+
disabled,
|
|
22
|
+
...rest,
|
|
23
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSwitch.Thumb, { className: "nuri-switch__thumb" })
|
|
24
|
+
}
|
|
25
|
+
),
|
|
26
|
+
label != null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "label", { htmlFor: id, className: "nuri-switch__label", children: label })
|
|
27
|
+
] });
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
exports.Switch = Switch;
|
|
33
|
+
//# sourceMappingURL=chunk-PAXRFQUJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-PAXRFQUJ.cjs","../src/Switch/Switch.tsx"],"names":["Switch"],"mappings":"AAAA,2cAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACA;ACHA,+BAAO;AACP,8GAA6B;AAC7B,8BAAkC;AAyC9B,+CAAA;AARG,IAAM,OAAA,EAAS,+BAAA,SAAoDA,OAAAA,CACxE,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,SAAA,EAAW,GAAG,KAAK,CAAA,EAC1D,GAAA,EACA;AACA,EAAA,MAAM,QAAA,EAAU,0BAAA,CAAM;AACtB,EAAA,MAAM,GAAA,mBAAK,MAAA,UAAU,CAAA,YAAA,EAAe,OAAO,CAAA,GAAA;AAGpC,EAAA;AACH,oBAAA;AAAa,MAAA;AAAZ,MAAA;AACC,QAAA;AACA,QAAA;AACU,QAAA;AACV,QAAA;AACI,QAAA;AAES,QAAA;AAAqC,MAAA;AACpD,IAAA;AAEG,IAAA;AAIL,EAAA;AAEH;ADlC6C;AACA;AACA;AACA","file":"/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-PAXRFQUJ.cjs","sourcesContent":[null,"'use client';\n\nimport './styles.css';\nimport * as RadixSwitch from '@radix-ui/react-switch';\nimport { forwardRef, useId } from 'react';\nimport type { ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\nexport interface SwitchProps {\n /**\n * 라벨 (컨트롤 우측). 디자인 시스템의 Toggle은 컨트롤 단독 정의지만,\n * 범용 사용을 위해 라벨을 지원한다(Checkbox 라벨 스타일 준용). 없으면 `aria-label` 필수.\n */\n label?: ReactNode;\n /** 켜짐 상태 (제어형). */\n checked?: boolean;\n /** 초기 상태 (비제어형). */\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n disabled?: boolean;\n /** 폼 전송용 name. */\n name?: string;\n /** 폼 전송 시 값. @default 'on' */\n value?: string;\n required?: boolean;\n id?: string;\n className?: string;\n 'aria-label'?: string;\n}\n\n/**\n * 스위치(토글). Radix Switch 기반 — `role=\"switch\"`·Space/Enter 토글·폼 참여 자동.\n * 즉시 적용되는 켬/끔 설정에 사용한다 (제출이 필요한 선택은 Checkbox).\n *\n * @example\n * <Switch label=\"알림 받기\" checked={on} onCheckedChange={setOn} />\n */\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(function Switch(\n { label, disabled = false, id: idProp, className, ...rest },\n ref,\n) {\n const reactId = useId();\n const id = idProp ?? `nuri-switch-${reactId}`;\n\n return (\n <div className={cx('nuri-switch', className)}>\n <RadixSwitch.Root\n ref={ref}\n id={id}\n className=\"nuri-switch__control\"\n disabled={disabled}\n {...rest}\n >\n <RadixSwitch.Thumb className=\"nuri-switch__thumb\" />\n </RadixSwitch.Root>\n {label != null && (\n <label htmlFor={id} className=\"nuri-switch__label\">\n {label}\n </label>\n )}\n </div>\n );\n});\n"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }'use client';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkR4E4BIPCcjs = require('./chunk-R4E4BIPC.cjs');
|
|
5
|
+
|
|
6
|
+
// src/Select/Select.tsx
|
|
7
|
+
require('./Select/styles.css');
|
|
8
|
+
var _reactselect = require('@radix-ui/react-select'); var RadixSelect = _interopRequireWildcard(_reactselect);
|
|
9
|
+
var _react = require('react');
|
|
10
|
+
var _jsxruntime = require('react/jsx-runtime');
|
|
11
|
+
var CaretIcon = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { d: "M1.1 2.5h5.8L4 5.9z", fill: "currentColor" }) });
|
|
12
|
+
var Select = _react.forwardRef.call(void 0, function Select2({
|
|
13
|
+
options,
|
|
14
|
+
size = "md",
|
|
15
|
+
placeholder,
|
|
16
|
+
value,
|
|
17
|
+
defaultValue,
|
|
18
|
+
onValueChange,
|
|
19
|
+
open,
|
|
20
|
+
defaultOpen,
|
|
21
|
+
onOpenChange,
|
|
22
|
+
disabled = false,
|
|
23
|
+
block = false,
|
|
24
|
+
name,
|
|
25
|
+
required,
|
|
26
|
+
container,
|
|
27
|
+
className,
|
|
28
|
+
"aria-label": ariaLabel
|
|
29
|
+
}, ref) {
|
|
30
|
+
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
31
|
+
RadixSelect.Root,
|
|
32
|
+
{
|
|
33
|
+
value,
|
|
34
|
+
defaultValue,
|
|
35
|
+
onValueChange,
|
|
36
|
+
open,
|
|
37
|
+
defaultOpen,
|
|
38
|
+
onOpenChange,
|
|
39
|
+
disabled,
|
|
40
|
+
name,
|
|
41
|
+
required,
|
|
42
|
+
children: [
|
|
43
|
+
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
44
|
+
RadixSelect.Trigger,
|
|
45
|
+
{
|
|
46
|
+
ref,
|
|
47
|
+
"aria-label": ariaLabel,
|
|
48
|
+
className: _chunkR4E4BIPCcjs.cx.call(void 0,
|
|
49
|
+
"nuri-select__trigger",
|
|
50
|
+
`nuri-select__trigger--${size}`,
|
|
51
|
+
block && "nuri-select__trigger--block",
|
|
52
|
+
className
|
|
53
|
+
),
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "nuri-select__value", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.Value, { placeholder }) }),
|
|
56
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.Icon, { className: "nuri-select__caret", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CaretIcon, {}) })
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.Portal, { container, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.Content, { className: "nuri-select__content", position: "popper", sideOffset: 6, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.Viewport, { className: "nuri-select__viewport", children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
61
|
+
RadixSelect.Item,
|
|
62
|
+
{
|
|
63
|
+
value: option.value,
|
|
64
|
+
disabled: option.disabled,
|
|
65
|
+
className: "nuri-select__item",
|
|
66
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RadixSelect.ItemText, { children: option.label })
|
|
67
|
+
},
|
|
68
|
+
option.value
|
|
69
|
+
)) }) }) })
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
exports.Select = Select;
|
|
78
|
+
//# sourceMappingURL=chunk-PC3B67B4.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-PC3B67B4.cjs","../src/Select/Select.tsx"],"names":["Select"],"mappings":"AAAA,uWAAY;AACZ;AACE;AACF,wDAA6B;AAC7B;AACA;ACHA,+BAAO;AACP,8GAA6B;AAC7B,8BAA2B;AAgDvB,+CAAA;AAFJ,IAAM,UAAA,EAAY,CAAA,EAAA,mBAChB,6BAAA,KAAC,EAAA,EAAI,KAAA,EAAM,GAAA,EAAI,MAAA,EAAO,GAAA,EAAI,OAAA,EAAQ,SAAA,EAAU,IAAA,EAAK,MAAA,EAAO,aAAA,EAAY,MAAA,EAClE,QAAA,kBAAA,6BAAA,MAAC,EAAA,EAAK,CAAA,EAAE,qBAAA,EAAsB,IAAA,EAAK,eAAA,CAAe,EAAA,CACpD,CAAA;AAoBK,IAAM,OAAA,EAAS,+BAAA,SAAoDA,OAAAA,CACxE;AAAA,EACE,OAAA;AAAA,EACA,KAAA,EAAO,IAAA;AAAA,EACP,WAAA;AAAA,EACA,KAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,IAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA,EAAW,KAAA;AAAA,EACX,MAAA,EAAQ,KAAA;AAAA,EACR,IAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA,EAAc;AAChB,CAAA,EACA,GAAA,EACA;AACA,EAAA,uBACE,8BAAA;AAAA,IAAa,WAAA,CAAA,IAAA;AAAA,IAAZ;AAAA,MACC,KAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MACA,IAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,8BAAA;AAAA,UAAa,WAAA,CAAA,OAAA;AAAA,UAAZ;AAAA,YACC,GAAA;AAAA,YACA,YAAA,EAAY,SAAA;AAAA,YACZ,SAAA,EAAW,kCAAA;AAAA,cACT,sBAAA;AAAA,cACA,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAA;AACpB,cAAA;AACT,cAAA;AACF,YAAA;AAEA,YAAA;AAAM,8BAAA;AAGO,8BAAA;AAEb,YAAA;AAAA,UAAA;AACF,QAAA;AAEa,wBAAA;AAIQ,UAAA;AAAZ,UAAA;AAEe,YAAA;AACG,YAAA;AACP,YAAA;AAEG,YAAA;AAAuB,UAAA;AALxB,UAAA;AAUtB,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEH;ADrE2C;AACA;AACA;AACA","file":"/Users/summerhoony/Desktop/projects/nuri-ui/dist/chunk-PC3B67B4.cjs","sourcesContent":[null,"'use client';\n\nimport './styles.css';\nimport * as RadixSelect from '@radix-ui/react-select';\nimport { forwardRef } from 'react';\nimport type { ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\ntype Size = 'sm' | 'md';\n\nexport interface SelectOption {\n value: string;\n label: ReactNode;\n disabled?: boolean;\n}\n\nexport interface SelectProps {\n /** 선택지 목록. */\n options: SelectOption[];\n /**\n * 사이즈. sm 36 / md 42 px 높이 (디자인 시스템의 Small/Large).\n * @default 'md'\n */\n size?: Size;\n /** 값이 없을 때 트리거에 표시할 문구. */\n placeholder?: ReactNode;\n /** 선택된 값 (제어형). */\n value?: string;\n /** 초기 값 (비제어형). */\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n /** 열림 상태 제어 (선택). */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n disabled?: boolean;\n /** 컨테이너 전체 너비로 확장. @default false */\n block?: boolean;\n /** 폼 전송용 name — 네이티브 select처럼 폼에 참여. */\n name?: string;\n required?: boolean;\n /** 포털 렌더 대상. 기본 document.body. */\n container?: HTMLElement | null;\n /** 트리거에 추가할 className. */\n className?: string;\n /** 시각 라벨이 없을 때 접근 가능한 이름. */\n 'aria-label'?: string;\n}\n\n/** 디자인 시스템의 8px 삼각 캐럿 (열림 시 CSS로 회전). */\nconst CaretIcon = () => (\n <svg width=\"8\" height=\"8\" viewBox=\"0 0 8 8\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M1.1 2.5h5.8L4 5.9z\" fill=\"currentColor\" />\n </svg>\n);\n\n/**\n * 셀렉트 박스 (단일 선택). Radix Select 기반 — 키보드 탐색·타입어헤드·\n * 포지셔닝·aria 연결을 자동 제공. 옵션 목록은 `options` 배열로 전달한다.\n *\n * 다중 선택(체크박스 옵션)·서브메뉴 변형은 별도 컴포넌트(DropdownMenu) 범위.\n *\n * @example\n * <Select\n * aria-label=\"정렬\"\n * placeholder=\"정렬 선택\"\n * options={[\n * { value: 'latest', label: '최신순' },\n * { value: 'edited', label: '수정순' },\n * ]}\n * onValueChange={setSort}\n * />\n */\nexport const Select = forwardRef<HTMLButtonElement, SelectProps>(function Select(\n {\n options,\n size = 'md',\n placeholder,\n value,\n defaultValue,\n onValueChange,\n open,\n defaultOpen,\n onOpenChange,\n disabled = false,\n block = false,\n name,\n required,\n container,\n className,\n 'aria-label': ariaLabel,\n },\n ref,\n) {\n return (\n <RadixSelect.Root\n value={value}\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n open={open}\n defaultOpen={defaultOpen}\n onOpenChange={onOpenChange}\n disabled={disabled}\n name={name}\n required={required}\n >\n <RadixSelect.Trigger\n ref={ref}\n aria-label={ariaLabel}\n className={cx(\n 'nuri-select__trigger',\n `nuri-select__trigger--${size}`,\n block && 'nuri-select__trigger--block',\n className,\n )}\n >\n <span className=\"nuri-select__value\">\n <RadixSelect.Value placeholder={placeholder} />\n </span>\n <RadixSelect.Icon className=\"nuri-select__caret\">\n <CaretIcon />\n </RadixSelect.Icon>\n </RadixSelect.Trigger>\n\n <RadixSelect.Portal container={container}>\n <RadixSelect.Content className=\"nuri-select__content\" position=\"popper\" sideOffset={6}>\n <RadixSelect.Viewport className=\"nuri-select__viewport\">\n {options.map((option) => (\n <RadixSelect.Item\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n className=\"nuri-select__item\"\n >\n <RadixSelect.ItemText>{option.label}</RadixSelect.ItemText>\n </RadixSelect.Item>\n ))}\n </RadixSelect.Viewport>\n </RadixSelect.Content>\n </RadixSelect.Portal>\n </RadixSelect.Root>\n );\n});\n"]}
|