@xfilecom/front-core 0.1.0 → 0.2.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/base.css ADDED
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Global base + atomic classes for @xfilecom/front-core components.
3
+ * Import after tokens.css.
4
+ */
5
+
6
+ *,
7
+ *::before,
8
+ *::after {
9
+ box-sizing: border-box;
10
+ }
11
+
12
+ body {
13
+ margin: 0;
14
+ min-height: 100dvh;
15
+ font-family: var(--xfc-font-sans);
16
+ font-size: var(--xfc-text-body);
17
+ line-height: var(--xfc-leading-normal);
18
+ color: var(--xfc-fg);
19
+ background: var(--xfc-bg);
20
+ -webkit-font-smoothing: antialiased;
21
+ }
22
+
23
+ a {
24
+ color: var(--xfc-accent);
25
+ text-decoration-thickness: 1px;
26
+ text-underline-offset: 2px;
27
+ }
28
+
29
+ a:hover {
30
+ color: var(--xfc-accent-hover);
31
+ }
32
+
33
+ /* —— Typography atoms —— */
34
+
35
+ .xfc-text {
36
+ margin: 0;
37
+ color: var(--xfc-fg);
38
+ }
39
+
40
+ .xfc-text--title {
41
+ font-size: var(--xfc-text-display);
42
+ font-weight: 700;
43
+ line-height: var(--xfc-leading-tight);
44
+ letter-spacing: -0.02em;
45
+ }
46
+
47
+ .xfc-text--appbar {
48
+ font-size: var(--xfc-text-appbar);
49
+ font-weight: 700;
50
+ line-height: 1.2;
51
+ color: var(--xfc-fg-strong);
52
+ }
53
+
54
+ .xfc-text--section {
55
+ font-size: var(--xfc-text-section);
56
+ font-weight: 700;
57
+ line-height: 1.3;
58
+ color: var(--xfc-fg-label);
59
+ }
60
+
61
+ .xfc-text--subtitle {
62
+ font-size: var(--xfc-text-section);
63
+ font-weight: 600;
64
+ line-height: var(--xfc-leading-tight);
65
+ }
66
+
67
+ .xfc-text--body {
68
+ font-size: var(--xfc-text-body);
69
+ }
70
+
71
+ .xfc-text--small {
72
+ font-size: var(--xfc-text-small);
73
+ }
74
+
75
+ .xfc-text--muted {
76
+ color: var(--xfc-fg-muted);
77
+ }
78
+
79
+ .xfc-text--accent {
80
+ color: var(--xfc-accent);
81
+ }
82
+
83
+ .xfc-text--label-block {
84
+ font-size: var(--xfc-text-body);
85
+ line-height: var(--xfc-leading-label);
86
+ color: var(--xfc-fg-label);
87
+ }
88
+
89
+ /* —— Layout —— */
90
+
91
+ .xfc-stack {
92
+ display: flex;
93
+ }
94
+
95
+ .xfc-stack--column {
96
+ flex-direction: column;
97
+ }
98
+
99
+ .xfc-stack--row {
100
+ flex-direction: row;
101
+ flex-wrap: wrap;
102
+ }
103
+
104
+ .xfc-stack--gap-none {
105
+ gap: 0;
106
+ }
107
+ .xfc-stack--gap-sm {
108
+ gap: var(--xfc-space-sm);
109
+ }
110
+ .xfc-stack--gap-md {
111
+ gap: var(--xfc-space-md);
112
+ }
113
+ .xfc-stack--gap-lg {
114
+ gap: var(--xfc-space-lg);
115
+ }
116
+
117
+ .xfc-stack--align-start {
118
+ align-items: flex-start;
119
+ }
120
+ .xfc-stack--align-center {
121
+ align-items: center;
122
+ }
123
+ .xfc-stack--align-stretch {
124
+ align-items: stretch;
125
+ }
126
+
127
+ .xfc-box {
128
+ display: block;
129
+ }
130
+
131
+ .xfc-box--p-sm {
132
+ padding: var(--xfc-space-sm);
133
+ }
134
+ .xfc-box--p-md {
135
+ padding: var(--xfc-space-md);
136
+ }
137
+ .xfc-box--p-lg {
138
+ padding: var(--xfc-space-lg);
139
+ }
140
+
141
+ .xfc-card {
142
+ background: var(--xfc-bg-elevated);
143
+ color: var(--xfc-fg);
144
+ border: 1px solid var(--xfc-border);
145
+ border-radius: var(--xfc-radius-md);
146
+ box-shadow: var(--xfc-card-shadow);
147
+ }
148
+
149
+ /* —— Buttons (피그마: 80×34 primary, radius 5) —— */
150
+
151
+ .xfc-btn {
152
+ display: inline-flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ gap: var(--xfc-space-xs);
156
+ min-height: 34px;
157
+ padding: 0 var(--xfc-space-lg);
158
+ font: inherit;
159
+ font-size: var(--xfc-text-body);
160
+ font-weight: 700;
161
+ line-height: 1;
162
+ border-radius: var(--xfc-radius-xs);
163
+ border: 1px solid transparent;
164
+ cursor: pointer;
165
+ transition:
166
+ background 0.15s ease,
167
+ color 0.15s ease,
168
+ border-color 0.15s ease,
169
+ box-shadow 0.15s ease;
170
+ }
171
+
172
+ .xfc-btn:focus-visible {
173
+ outline: none;
174
+ box-shadow: var(--xfc-focus-ring);
175
+ }
176
+
177
+ .xfc-btn:disabled {
178
+ opacity: 0.5;
179
+ cursor: not-allowed;
180
+ }
181
+
182
+ .xfc-btn--primary {
183
+ background: var(--xfc-accent);
184
+ color: var(--xfc-accent-fg);
185
+ }
186
+
187
+ .xfc-btn--primary:hover:not(:disabled) {
188
+ background: var(--xfc-accent-hover);
189
+ }
190
+
191
+ .xfc-btn--secondary {
192
+ background: var(--xfc-bg-elevated);
193
+ color: var(--xfc-fg);
194
+ border-color: var(--xfc-border-strong);
195
+ }
196
+
197
+ .xfc-btn--secondary:hover:not(:disabled) {
198
+ border-color: var(--xfc-fg-muted);
199
+ }
200
+
201
+ .xfc-btn--outline {
202
+ background: var(--xfc-bg-elevated);
203
+ color: var(--xfc-accent);
204
+ border-color: var(--xfc-accent);
205
+ }
206
+
207
+ .xfc-btn--outline:hover:not(:disabled) {
208
+ background: color-mix(in srgb, var(--xfc-accent) 6%, transparent);
209
+ }
210
+
211
+ .xfc-btn--muted {
212
+ background: var(--xfc-bg-disabled);
213
+ color: var(--xfc-fg-muted);
214
+ border-color: transparent;
215
+ }
216
+
217
+ .xfc-btn--muted:hover:not(:disabled) {
218
+ filter: brightness(0.97);
219
+ }
220
+
221
+ .xfc-btn--ghost {
222
+ background: transparent;
223
+ color: var(--xfc-accent);
224
+ }
225
+
226
+ .xfc-btn--ghost:hover:not(:disabled) {
227
+ background: color-mix(in srgb, var(--xfc-accent) 8%, transparent);
228
+ }
229
+
230
+ /* —— Inputs (로그인 필드 48px, border #D4D4D4) —— */
231
+
232
+ .xfc-input {
233
+ display: block;
234
+ width: 100%;
235
+ min-height: 48px;
236
+ padding: 0 var(--xfc-space-lg);
237
+ font: inherit;
238
+ font-size: var(--xfc-text-input);
239
+ color: var(--xfc-fg);
240
+ background: var(--xfc-bg-elevated);
241
+ border: 1px solid var(--xfc-border-strong);
242
+ border-radius: var(--xfc-radius-xs);
243
+ box-shadow: var(--xfc-input-shadow);
244
+ transition:
245
+ border-color 0.15s ease,
246
+ box-shadow 0.15s ease;
247
+ }
248
+
249
+ .xfc-input::placeholder {
250
+ color: var(--xfc-fg-placeholder);
251
+ }
252
+
253
+ .xfc-input:focus {
254
+ outline: none;
255
+ border-color: var(--xfc-accent);
256
+ box-shadow: var(--xfc-input-shadow), var(--xfc-focus-ring);
257
+ }
258
+
259
+ .xfc-input:disabled {
260
+ opacity: 0.6;
261
+ cursor: not-allowed;
262
+ }
263
+
264
+ /* —— Badges —— */
265
+
266
+ .xfc-badge {
267
+ display: inline-flex;
268
+ align-items: center;
269
+ padding: 2px var(--xfc-space-sm);
270
+ font-size: var(--xfc-text-small);
271
+ font-weight: 600;
272
+ line-height: 1.3;
273
+ border-radius: var(--xfc-radius-xs);
274
+ }
275
+
276
+ .xfc-badge--neutral {
277
+ background: var(--xfc-border);
278
+ color: var(--xfc-fg);
279
+ }
280
+
281
+ .xfc-badge--accent {
282
+ background: color-mix(in srgb, var(--xfc-accent) 18%, transparent);
283
+ color: var(--xfc-accent-hover);
284
+ }
285
+
286
+ .xfc-badge--success {
287
+ background: var(--xfc-success-bg);
288
+ color: var(--xfc-success);
289
+ }
290
+
291
+ .xfc-badge--danger {
292
+ background: color-mix(in srgb, var(--xfc-danger) 15%, transparent);
293
+ color: var(--xfc-danger);
294
+ }
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ export type BadgeProps = HTMLAttributes<HTMLSpanElement> & {
3
+ tone?: 'neutral' | 'accent' | 'success' | 'danger';
4
+ children?: ReactNode;
5
+ };
6
+ export declare function Badge({ tone, className, children, ...rest }: BadgeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Badge = Badge;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Badge({ tone = 'neutral', className = '', children, ...rest }) {
6
+ const cls = ['xfc-badge', `xfc-badge--${tone}`, className].filter(Boolean).join(' ');
7
+ return ((0, jsx_runtime_1.jsx)("span", { className: cls, ...rest, children: children }));
8
+ }
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ export type BoxProps = HTMLAttributes<HTMLDivElement> & {
3
+ padding?: 'none' | 'sm' | 'md' | 'lg';
4
+ children?: ReactNode;
5
+ };
6
+ export declare function Box({ padding, className, children, ...rest }: BoxProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Box = Box;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Box({ padding = 'none', className = '', children, ...rest }) {
6
+ const padClass = padding === 'none' ? '' : padding === 'sm' ? 'xfc-box--p-sm' : padding === 'md' ? 'xfc-box--p-md' : 'xfc-box--p-lg';
7
+ const cls = ['xfc-box', padClass, className].filter(Boolean).join(' ');
8
+ return ((0, jsx_runtime_1.jsx)("div", { className: cls, ...rest, children: children }));
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { ButtonHTMLAttributes } from 'react';
2
+ export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
3
+ variant?: 'primary' | 'secondary' | 'outline' | 'muted' | 'ghost';
4
+ };
5
+ export declare function Button({ variant, className, type, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Button = Button;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Button({ variant = 'primary', className = '', type = 'button', ...rest }) {
6
+ const cls = ['xfc-btn', `xfc-btn--${variant}`, className].filter(Boolean).join(' ');
7
+ return (0, jsx_runtime_1.jsx)("button", { type: type, className: cls, ...rest });
8
+ }
@@ -0,0 +1,5 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ export type CardProps = HTMLAttributes<HTMLDivElement> & {
3
+ children?: ReactNode;
4
+ };
5
+ export declare function Card({ className, children, ...rest }: CardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Card = Card;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Card({ className = '', children, ...rest }) {
6
+ const cls = ['xfc-card', className].filter(Boolean).join(' ');
7
+ return ((0, jsx_runtime_1.jsx)("div", { className: cls, ...rest, children: children }));
8
+ }
@@ -0,0 +1,3 @@
1
+ import { type InputHTMLAttributes } from 'react';
2
+ export type InputProps = InputHTMLAttributes<HTMLInputElement>;
3
+ export declare const Input: import("react").ForwardRefExoticComponent<InputProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Input = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ exports.Input = (0, react_1.forwardRef)(function Input({ className = '', ...rest }, ref) {
7
+ const cls = ['xfc-input', className].filter(Boolean).join(' ');
8
+ return (0, jsx_runtime_1.jsx)("input", { ref: ref, className: cls, ...rest });
9
+ });
@@ -0,0 +1,8 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ export type StackProps = HTMLAttributes<HTMLDivElement> & {
3
+ direction?: 'row' | 'column';
4
+ gap?: 'none' | 'sm' | 'md' | 'lg';
5
+ align?: 'start' | 'center' | 'stretch';
6
+ children?: ReactNode;
7
+ };
8
+ export declare function Stack({ direction, gap, align, className, children, ...rest }: StackProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Stack = Stack;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function Stack({ direction = 'column', gap = 'md', align = 'start', className = '', children, ...rest }) {
6
+ const cls = [
7
+ 'xfc-stack',
8
+ direction === 'column' ? 'xfc-stack--column' : 'xfc-stack--row',
9
+ `xfc-stack--gap-${gap}`,
10
+ `xfc-stack--align-${align}`,
11
+ className,
12
+ ]
13
+ .filter(Boolean)
14
+ .join(' ');
15
+ return ((0, jsx_runtime_1.jsx)("div", { className: cls, ...rest, children: children }));
16
+ }
@@ -0,0 +1,22 @@
1
+ import { type ElementType, type HTMLAttributes, type ReactNode } from 'react';
2
+ declare const variantClass: {
3
+ readonly title: "xfc-text xfc-text--title";
4
+ readonly appbar: "xfc-text xfc-text--appbar";
5
+ readonly section: "xfc-text xfc-text--section";
6
+ readonly subtitle: "xfc-text xfc-text--subtitle";
7
+ readonly body: "xfc-text xfc-text--body";
8
+ readonly muted: "xfc-text xfc-text--body xfc-text--muted";
9
+ readonly small: "xfc-text xfc-text--small";
10
+ readonly label: "xfc-text xfc-text--small xfc-text--muted";
11
+ readonly labelBlock: "xfc-text xfc-text--label-block";
12
+ readonly accent: "xfc-text xfc-text--body xfc-text--accent";
13
+ };
14
+ export type TextVariant = keyof typeof variantClass;
15
+ export type TextProps = {
16
+ as?: ElementType;
17
+ variant?: TextVariant;
18
+ children?: ReactNode;
19
+ className?: string;
20
+ } & HTMLAttributes<HTMLElement>;
21
+ export declare function Text({ as, variant, className, children, ...rest }: TextProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
22
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Text = Text;
4
+ const react_1 = require("react");
5
+ const variantClass = {
6
+ title: 'xfc-text xfc-text--title',
7
+ appbar: 'xfc-text xfc-text--appbar',
8
+ section: 'xfc-text xfc-text--section',
9
+ subtitle: 'xfc-text xfc-text--subtitle',
10
+ body: 'xfc-text xfc-text--body',
11
+ muted: 'xfc-text xfc-text--body xfc-text--muted',
12
+ small: 'xfc-text xfc-text--small',
13
+ label: 'xfc-text xfc-text--small xfc-text--muted',
14
+ labelBlock: 'xfc-text xfc-text--label-block',
15
+ accent: 'xfc-text xfc-text--body xfc-text--accent',
16
+ };
17
+ function Text({ as = 'p', variant = 'body', className = '', children, ...rest }) {
18
+ const cls = [variantClass[variant], className].filter(Boolean).join(' ');
19
+ return (0, react_1.createElement)(as, { className: cls, ...rest }, children);
20
+ }
@@ -0,0 +1,7 @@
1
+ export { Badge, type BadgeProps } from './Badge';
2
+ export { Box, type BoxProps } from './Box';
3
+ export { Button, type ButtonProps } from './Button';
4
+ export { Card, type CardProps } from './Card';
5
+ export { Input, type InputProps } from './Input';
6
+ export { Stack, type StackProps } from './Stack';
7
+ export { Text, type TextProps, type TextVariant } from './Text';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Text = exports.Stack = exports.Input = exports.Card = exports.Button = exports.Box = exports.Badge = void 0;
4
+ var Badge_1 = require("./Badge");
5
+ Object.defineProperty(exports, "Badge", { enumerable: true, get: function () { return Badge_1.Badge; } });
6
+ var Box_1 = require("./Box");
7
+ Object.defineProperty(exports, "Box", { enumerable: true, get: function () { return Box_1.Box; } });
8
+ var Button_1 = require("./Button");
9
+ Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return Button_1.Button; } });
10
+ var Card_1 = require("./Card");
11
+ Object.defineProperty(exports, "Card", { enumerable: true, get: function () { return Card_1.Card; } });
12
+ var Input_1 = require("./Input");
13
+ Object.defineProperty(exports, "Input", { enumerable: true, get: function () { return Input_1.Input; } });
14
+ var Stack_1 = require("./Stack");
15
+ Object.defineProperty(exports, "Stack", { enumerable: true, get: function () { return Stack_1.Stack; } });
16
+ var Text_1 = require("./Text");
17
+ Object.defineProperty(exports, "Text", { enumerable: true, get: function () { return Text_1.Text; } });
package/dist/index.d.ts CHANGED
@@ -1,12 +1,38 @@
1
1
  /**
2
- * @xfilecom/front-core — design tokens (components expand later).
3
- * CSS: import '@xfilecom/front-core/tokens.css' in Vite/React entry.
2
+ * @xfilecom/front-core — design tokens + atomic React components (browser-only).
3
+ *
4
+ * CSS (앱 엔트리에서 순서대로):
5
+ * import '@xfilecom/front-core/tokens.css';
6
+ * import '@xfilecom/front-core/base.css';
4
7
  */
5
- export declare const XFRAME_FRONT_CORE_VERSION = "0.1.0";
8
+ export declare const XFRAME_FRONT_CORE_VERSION = "0.2.1";
9
+ /** CSS 커스텀 프로퍼티 이름 (-- 제외 시 var()와 함께 사용) */
6
10
  export declare const tokenVars: {
7
11
  readonly colorBg: "--xfc-bg";
12
+ readonly colorBgElevated: "--xfc-bg-elevated";
13
+ readonly colorBgMuted: "--xfc-bg-muted";
8
14
  readonly colorFg: "--xfc-fg";
15
+ readonly colorFgMuted: "--xfc-fg-muted";
16
+ readonly colorBorder: "--xfc-border";
17
+ readonly colorBorderStrong: "--xfc-border-strong";
9
18
  readonly colorAccent: "--xfc-accent";
19
+ readonly colorAccentHover: "--xfc-accent-hover";
20
+ readonly colorDanger: "--xfc-danger";
21
+ readonly radiusXs: "--xfc-radius-xs";
10
22
  readonly radiusSm: "--xfc-radius-sm";
23
+ readonly radiusMd: "--xfc-radius-md";
24
+ readonly radiusLg: "--xfc-radius-lg";
25
+ readonly spaceXs: "--xfc-space-xs";
26
+ readonly spaceSm: "--xfc-space-sm";
11
27
  readonly spaceMd: "--xfc-space-md";
28
+ readonly spaceLg: "--xfc-space-lg";
29
+ readonly spaceXl: "--xfc-space-xl";
30
+ readonly space2xl: "--xfc-space-2xl";
31
+ readonly fontSans: "--xfc-font-sans";
32
+ readonly textDisplay: "--xfc-text-display";
33
+ readonly textAppbar: "--xfc-text-appbar";
34
+ readonly textSection: "--xfc-text-section";
35
+ readonly textBody: "--xfc-text-body";
36
+ readonly textSmall: "--xfc-text-small";
12
37
  };
38
+ export { Badge, Box, Button, Card, Input, Stack, Text, type BadgeProps, type BoxProps, type ButtonProps, type CardProps, type InputProps, type StackProps, type TextProps, type TextVariant, } from './components';
package/dist/index.js CHANGED
@@ -1,15 +1,48 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tokenVars = exports.XFRAME_FRONT_CORE_VERSION = void 0;
3
+ exports.Text = exports.Stack = exports.Input = exports.Card = exports.Button = exports.Box = exports.Badge = exports.tokenVars = exports.XFRAME_FRONT_CORE_VERSION = void 0;
4
4
  /**
5
- * @xfilecom/front-core — design tokens (components expand later).
6
- * CSS: import '@xfilecom/front-core/tokens.css' in Vite/React entry.
5
+ * @xfilecom/front-core — design tokens + atomic React components (browser-only).
6
+ *
7
+ * CSS (앱 엔트리에서 순서대로):
8
+ * import '@xfilecom/front-core/tokens.css';
9
+ * import '@xfilecom/front-core/base.css';
7
10
  */
8
- exports.XFRAME_FRONT_CORE_VERSION = '0.1.0';
11
+ exports.XFRAME_FRONT_CORE_VERSION = '0.2.1';
12
+ /** CSS 커스텀 프로퍼티 이름 (-- 제외 시 var()와 함께 사용) */
9
13
  exports.tokenVars = {
10
14
  colorBg: '--xfc-bg',
15
+ colorBgElevated: '--xfc-bg-elevated',
16
+ colorBgMuted: '--xfc-bg-muted',
11
17
  colorFg: '--xfc-fg',
18
+ colorFgMuted: '--xfc-fg-muted',
19
+ colorBorder: '--xfc-border',
20
+ colorBorderStrong: '--xfc-border-strong',
12
21
  colorAccent: '--xfc-accent',
22
+ colorAccentHover: '--xfc-accent-hover',
23
+ colorDanger: '--xfc-danger',
24
+ radiusXs: '--xfc-radius-xs',
13
25
  radiusSm: '--xfc-radius-sm',
26
+ radiusMd: '--xfc-radius-md',
27
+ radiusLg: '--xfc-radius-lg',
28
+ spaceXs: '--xfc-space-xs',
29
+ spaceSm: '--xfc-space-sm',
14
30
  spaceMd: '--xfc-space-md',
31
+ spaceLg: '--xfc-space-lg',
32
+ spaceXl: '--xfc-space-xl',
33
+ space2xl: '--xfc-space-2xl',
34
+ fontSans: '--xfc-font-sans',
35
+ textDisplay: '--xfc-text-display',
36
+ textAppbar: '--xfc-text-appbar',
37
+ textSection: '--xfc-text-section',
38
+ textBody: '--xfc-text-body',
39
+ textSmall: '--xfc-text-small',
15
40
  };
41
+ var components_1 = require("./components");
42
+ Object.defineProperty(exports, "Badge", { enumerable: true, get: function () { return components_1.Badge; } });
43
+ Object.defineProperty(exports, "Box", { enumerable: true, get: function () { return components_1.Box; } });
44
+ Object.defineProperty(exports, "Button", { enumerable: true, get: function () { return components_1.Button; } });
45
+ Object.defineProperty(exports, "Card", { enumerable: true, get: function () { return components_1.Card; } });
46
+ Object.defineProperty(exports, "Input", { enumerable: true, get: function () { return components_1.Input; } });
47
+ Object.defineProperty(exports, "Stack", { enumerable: true, get: function () { return components_1.Stack; } });
48
+ Object.defineProperty(exports, "Text", { enumerable: true, get: function () { return components_1.Text; } });
package/dist/tokens.css CHANGED
@@ -1,7 +1,75 @@
1
+ /**
2
+ * Design tokens — `xframe/html/html` (business-promotion Figma export) 기준.
3
+ * 참고: main.html, navi_default.html, login_01.html 등 인라인 스타일에서 추출.
4
+ */
1
5
  :root {
2
- --xfc-bg: #0f1419;
3
- --xfc-fg: #e7ecf3;
4
- --xfc-accent: #3b82f6;
5
- --xfc-radius-sm: 6px;
6
+ /* Surfaces */
7
+ --xfc-bg: #ffffff;
8
+ --xfc-bg-elevated: #ffffff;
9
+ --xfc-bg-muted: #f8f8f8;
10
+ --xfc-bg-disabled: #eaeaea;
11
+
12
+ /* Text */
13
+ --xfc-fg: #1c252f;
14
+ --xfc-fg-strong: #000000;
15
+ --xfc-fg-label: #1d2125;
16
+ --xfc-fg-muted: #777777;
17
+ --xfc-fg-placeholder: #c7c7c7;
18
+ --xfc-fg-icon: #464c50;
19
+
20
+ /* Lines */
21
+ --xfc-border: #ededed;
22
+ --xfc-border-strong: #d4d4d4;
23
+ --xfc-border-header: #e9e8e6;
24
+
25
+ /* Brand */
26
+ --xfc-accent: #2a5bff;
27
+ --xfc-accent-hover: #2248e6;
28
+ --xfc-accent-fg: #ffffff;
29
+
30
+ /* Status */
31
+ --xfc-danger: #f43b3c;
32
+ --xfc-success: #059669;
33
+ --xfc-success-bg: #d1fae5;
34
+ --xfc-warning: #d97706;
35
+ --xfc-warning-bg: #fef3c7;
36
+
37
+ /* Effects */
38
+ --xfc-input-shadow: 0 7px 64px rgba(0, 0, 0, 0.07);
39
+ --xfc-card-shadow: 0 1px 2px rgba(28, 37, 47, 0.06);
40
+
41
+ /* Radius (px 그대로 — 디자인 5 / 10 / pill) */
42
+ --xfc-radius-xs: 5px;
43
+ --xfc-radius-sm: 5px;
44
+ --xfc-radius-md: 10px;
45
+ --xfc-radius-lg: 10px;
46
+ --xfc-radius-full: 9999px;
47
+
48
+ /* Space */
49
+ --xfc-space-xs: 4px;
50
+ --xfc-space-sm: 8px;
6
51
  --xfc-space-md: 12px;
52
+ --xfc-space-lg: 16px;
53
+ --xfc-space-xl: 24px;
54
+ --xfc-space-2xl: 32px;
55
+
56
+ /* Typography — Pretendard Variable (+ 로고용 Poppins 는 앱에서 별도) */
57
+ --xfc-font-sans: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, system-ui,
58
+ Roboto, 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
59
+ --xfc-font-mono: ui-monospace, 'Cascadia Code', 'SF Mono', Menlo, monospace;
60
+
61
+ --xfc-text-display: 2.5rem;
62
+ --xfc-text-appbar: 1.375rem;
63
+ --xfc-text-section: 1.125rem;
64
+ --xfc-text-body: 1rem;
65
+ --xfc-text-small: 0.875rem;
66
+ --xfc-text-input: 0.9375rem;
67
+
68
+ --xfc-leading-tight: 1.25;
69
+ --xfc-leading-normal: 1.5;
70
+ --xfc-leading-label: 22px;
71
+ --xfc-leading-menu: 50px;
72
+
73
+ /* Focus */
74
+ --xfc-focus-ring: 0 0 0 3px color-mix(in srgb, var(--xfc-accent) 35%, transparent);
7
75
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xfilecom/front-core",
3
- "version": "0.1.0",
4
- "description": "Shared React tokens (browser-only; no Nest dependency)",
3
+ "version": "0.2.2",
4
+ "description": "Shared design tokens, base CSS, and atomic React components (browser-only; no Nest dependency)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
@@ -9,22 +9,29 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "default": "./dist/index.js"
11
11
  },
12
- "./tokens.css": "./dist/tokens.css"
12
+ "./tokens.css": "./dist/tokens.css",
13
+ "./base.css": "./dist/base.css"
13
14
  },
14
- "files": ["dist"],
15
+ "files": [
16
+ "dist"
17
+ ],
15
18
  "scripts": {
16
19
  "prepublishOnly": "npm run build",
17
20
  "build": "npm run build:ts && npm run build:css",
18
21
  "build:ts": "tsc",
19
- "build:css": "cp src/tokens.css dist/tokens.css"
22
+ "build:css": "cp src/tokens.css dist/tokens.css && cp src/base.css dist/base.css"
20
23
  },
21
24
  "peerDependencies": {
22
25
  "react": ">=18.0.0",
23
26
  "react-dom": ">=18.0.0"
24
27
  },
25
28
  "peerDependenciesMeta": {
26
- "react": { "optional": true },
27
- "react-dom": { "optional": true }
29
+ "react": {
30
+ "optional": true
31
+ },
32
+ "react-dom": {
33
+ "optional": true
34
+ }
28
35
  },
29
36
  "devDependencies": {
30
37
  "@types/react": "^18.2.0",