@2urgseui/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.MD ADDED
@@ -0,0 +1,221 @@
1
+ # @2urgse/ui
2
+
3
+ Shared UI component library for 2URGSE products.
4
+ Built on Radix UI primitives, styled with Tailwind CSS, and driven by a first-class design token system.
5
+
6
+ ---
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install /path/to/build/2urgse-ui-0.1.0.tgz
12
+ # or once published:
13
+ npm install @2urgse/ui
14
+ ```
15
+
16
+ ### Peer dependencies
17
+
18
+ ```bash
19
+ npm install react react-dom lucide-react
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Tailwind setup
25
+
26
+ The library ships a Tailwind **preset** that wires in all design tokens — colors,
27
+ typography, spacing, shadows, border radii, motion, and breakpoints.
28
+ Your project's Tailwind config must extend it; **configs do not merge automatically**.
29
+
30
+ ### 1. Reference the preset
31
+
32
+ ```ts
33
+ // tailwind.config.ts (consuming project)
34
+ import { type Config } from "tailwindcss";
35
+ import uiPreset from "@2urgse/ui/tailwind";
36
+
37
+ export default {
38
+ presets: [uiPreset],
39
+
40
+ content: [
41
+ "./src/**/*.{ts,tsx}",
42
+ // Scan library dist so component classes are never purged
43
+ "./node_modules/@2urgse/ui/dist/**/*.{js,cjs}",
44
+ ],
45
+ } satisfies Config;
46
+ ```
47
+
48
+ ### 2. Inject CSS variables
49
+
50
+ The preset registers a Tailwind plugin that emits `:root` / `.dark` CSS custom
51
+ properties from the token color schemes. Include a global CSS file in your app
52
+ entry point to activate them:
53
+
54
+ ```css
55
+ /* globals.css */
56
+ @tailwind base;
57
+ @tailwind components;
58
+ @tailwind utilities;
59
+ ```
60
+
61
+ Dark mode is toggled via the `class` strategy — add `dark` to `<html>`:
62
+
63
+ ```ts
64
+ // e.g. next-themes, or manually
65
+ document.documentElement.classList.toggle("dark");
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Usage
71
+
72
+ ```tsx
73
+ import {
74
+ AppShell,
75
+ Button,
76
+ Heading,
77
+ Caption,
78
+ Icon,
79
+ Sidebar,
80
+ // ...
81
+ } from "@2urgse/ui";
82
+ ```
83
+
84
+ ### Design tokens (JavaScript/TypeScript)
85
+
86
+ ```ts
87
+ import {
88
+ colors,
89
+ spacing,
90
+ typography,
91
+ breakpoints,
92
+ boxShadow,
93
+ borderRadius,
94
+ transitionDuration,
95
+ transitionTimingFunction,
96
+ } from "@2urgse/ui/tokens";
97
+
98
+ // Use in JS logic, useMediaQuery, charting libs, etc.
99
+ const primaryColor = colors.brand[600]; // "#379e23"
100
+ const tabletWidth = breakpoints.tablet; // "768px"
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Components
106
+
107
+ ### Layout
108
+
109
+ | Component | Description |
110
+ |---|---|
111
+ | `AppShell` | Full-screen shell with glassmorphic sidebar and topbar |
112
+
113
+ ### Primitives
114
+
115
+ | Component | Variants / Notes |
116
+ |---|---|
117
+ | `Button` | `default` `destructive` `outline` `secondary` `ghost` `link` `glass` |
118
+ | `Heading` | `level` 1–6, `display` font, `size`, `weight`, `tone` |
119
+ | `Caption` | `figcaption` / `small` / `span` / `p`, optional leading `icon` |
120
+ | `Text` | `p` / `span` / `label` / `div`, `size`, `weight`, `tone` |
121
+ | `Icon` | Wraps any Lucide icon by `name` |
122
+ | `Badge` | Status and label badges |
123
+ | `Avatar` | User / entity avatar with fallback |
124
+ | `Card` | Surface card with header, content, footer slots |
125
+ | `Input` | Text input |
126
+ | `Textarea` | Multi-line input |
127
+ | `Select` | Dropdown select |
128
+ | `Checkbox` | Checkbox with label |
129
+ | `Switch` | Toggle switch |
130
+ | `RadioGroup` | Radio button group |
131
+ | `Slider` | Range slider |
132
+ | `Progress` | Progress bar |
133
+ | `Tabs` | Tab navigation |
134
+ | `Accordion` | Collapsible sections |
135
+ | `Collapsible` | Single collapsible panel |
136
+ | `Dialog` | Modal dialog |
137
+ | `Sheet` | Side-anchored sheet |
138
+ | `Drawer` | Bottom/side drawer (Vaul) |
139
+ | `AlertDialog` | Confirmation dialog |
140
+ | `Popover` | Floating popover |
141
+ | `DropdownMenu` | Dropdown menu |
142
+ | `Tooltip` | Hover tooltip |
143
+ | `Breadcrumb` | Navigation breadcrumb |
144
+ | `Pagination` | Page navigation |
145
+ | `Table` | Data table |
146
+ | `ScrollArea` | Custom scrollbar container |
147
+ | `Separator` | Horizontal / vertical divider |
148
+ | `Skeleton` | Loading placeholder |
149
+ | `Alert` | Inline alert / banner |
150
+ | `Calendar` | Date picker calendar |
151
+ | `InputOtp` | OTP code input |
152
+ | `Label` | Form label |
153
+ | `AspectRatio` | Aspect-ratio container |
154
+ | `RichTextArea` | Tiptap-based rich text editor |
155
+ | `Sidebar` | Full sidebar system with provider, menu, groups |
156
+
157
+ ---
158
+
159
+ ## Design tokens
160
+
161
+ All tokens live in `source/tokens/` and are the single source of truth for both
162
+ the Tailwind config and any JavaScript runtime usage.
163
+
164
+ | Token file | Exports | Example |
165
+ |---|---|---|
166
+ | `colors.ts` | `colors` | `colors.brand[600]`, `colors.schemes.light.background` |
167
+ | `spacing.ts` | `spacing` | `spacing[4]` → `"16px"` |
168
+ | `typography.ts` | `typography` | `typography.fontFamily.sans` |
169
+ | `breakpoints.ts` | `breakpoints` | `breakpoints.tablet` → `"768px"` |
170
+ | `radii.ts` | `borderRadius` | `borderRadius.lg` → `"0.5rem"` |
171
+ | `shadows.ts` | `boxShadow` | `boxShadow.md` |
172
+ | `motion.ts` | `transitionDuration`, `transitionTimingFunction` | `transitionDuration.slow` → `"300ms"` |
173
+
174
+ ### Breakpoints
175
+
176
+ | Name | Value | Use case |
177
+ |---|---|---|
178
+ | `mobile` / `xs` | 375px | Handheld |
179
+ | `sm` | 640px | Large phone |
180
+ | `tablet` / `md` | 768px | Tablet portrait |
181
+ | `lg` | 1024px | Laptop |
182
+ | `desktop` / `xl` | 1280px | Standard PC |
183
+ | `2xl` | 1536px | Wide desktop |
184
+ | `wide` / `3xl` | 1920px | Large display |
185
+
186
+ ---
187
+
188
+ ## Local development
189
+
190
+ ```bash
191
+ # Build library (watch mode)
192
+ npm run dev
193
+
194
+ # Build once
195
+ npm run build
196
+
197
+ # Pack tarball to ./build for local installation
198
+ npm run pack:build
199
+
200
+ # Run tests
201
+ npm run test
202
+
203
+ # Lint
204
+ npm run lint
205
+
206
+ # Storybook
207
+ npm run storybook
208
+
209
+ # Playground app
210
+ npm run playground
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Versioning
216
+
217
+ Follows [Semantic Versioning](https://semver.org):
218
+
219
+ - `patch` — bug fixes, no API change
220
+ - `minor` — new components or props (backward compatible)
221
+ - `major` — breaking API or token changes
@@ -0,0 +1,317 @@
1
+ // source/tokens/breakpoints.ts
2
+ var breakpoints = {
3
+ // ── Semantic ──────────────────────────────────────────────────────────
4
+ mobile: "375px",
5
+ tablet: "768px",
6
+ desktop: "1280px",
7
+ wide: "1920px",
8
+ // ── Numeric shorthands (mirrors Tailwind defaults for familiarity) ────
9
+ xs: "375px",
10
+ // handheld
11
+ sm: "640px",
12
+ // large phone / small tablet
13
+ md: "768px",
14
+ // tablet
15
+ lg: "1024px",
16
+ // laptop
17
+ xl: "1280px",
18
+ // desktop
19
+ "2xl": "1536px",
20
+ // wide desktop
21
+ "3xl": "1920px"
22
+ // large display
23
+ };
24
+
25
+ // source/tokens/colors.ts
26
+ var brand = {
27
+ 50: "#f6faf0",
28
+ 100: "#eef7e4",
29
+ 200: "#d4ebbe",
30
+ 300: "#bae09d",
31
+ 400: "#7dc75d",
32
+ 500: "#43b02b",
33
+ 600: "#379e23",
34
+ 700: "#2a8518",
35
+ 800: "#1c690f",
36
+ 900: "#124f09",
37
+ 950: "#093304"
38
+ };
39
+ var neutral = {
40
+ 0: "#ffffff",
41
+ 50: "#f9fafb",
42
+ 100: "#f3f4f6",
43
+ 200: "#e5e7eb",
44
+ 300: "#d1d5db",
45
+ 400: "#9ca3af",
46
+ 500: "#6b7280",
47
+ 600: "#4b5563",
48
+ 700: "#374151",
49
+ 800: "#1f2937",
50
+ 900: "#111827",
51
+ 950: "#030712"
52
+ };
53
+ var success = {
54
+ 50: "#f0fdf4",
55
+ 100: "#dcfce7",
56
+ 200: "#bbf7d0",
57
+ 300: "#86efac",
58
+ 400: "#4ade80",
59
+ 500: "#22c55e",
60
+ 600: "#16a34a",
61
+ 700: "#15803d",
62
+ 800: "#166534",
63
+ 900: "#14532d"
64
+ };
65
+ var warning = {
66
+ 50: "#fffbeb",
67
+ 100: "#fef3c7",
68
+ 200: "#fde68a",
69
+ 300: "#fcd34d",
70
+ 400: "#fbbf24",
71
+ 500: "#f59e0b",
72
+ 600: "#d97706",
73
+ 700: "#b45309",
74
+ 800: "#92400e",
75
+ 900: "#78350f"
76
+ };
77
+ var error = {
78
+ 50: "#fef2f2",
79
+ 100: "#fee2e2",
80
+ 200: "#fecaca",
81
+ 300: "#fca5a5",
82
+ 400: "#f87171",
83
+ 500: "#ef4444",
84
+ 600: "#dc2626",
85
+ 700: "#b91c1c",
86
+ 800: "#991b1b",
87
+ 900: "#7f1d1d"
88
+ };
89
+ var info = {
90
+ 50: "#eff6ff",
91
+ 100: "#dbeafe",
92
+ 200: "#bfdbfe",
93
+ 300: "#93c5fd",
94
+ 400: "#60a5fa",
95
+ 500: "#3b82f6",
96
+ 600: "#2563eb",
97
+ 700: "#1d4ed8",
98
+ 800: "#1e40af",
99
+ 900: "#1e3a8a"
100
+ };
101
+ var accent = {
102
+ 50: "#faf5ff",
103
+ 100: "#f3e8ff",
104
+ 200: "#e9d5ff",
105
+ 300: "#d8b4fe",
106
+ 400: "#c084fc",
107
+ 500: "#a855f7",
108
+ 600: "#9333ea",
109
+ 700: "#7c3aed",
110
+ 800: "#6b21a8",
111
+ 900: "#581c87"
112
+ };
113
+ var colors = {
114
+ brand,
115
+ neutral,
116
+ success,
117
+ warning,
118
+ error,
119
+ info,
120
+ accent,
121
+ /** Resolved semantic aliases for light-UI usage (concrete colors, not path strings) */
122
+ semantic: {
123
+ primary: brand[600],
124
+ primaryHover: brand[700],
125
+ primaryForeground: neutral[0],
126
+ secondary: neutral[100],
127
+ secondaryHover: neutral[200],
128
+ secondaryForeground: neutral[900],
129
+ success: success[600],
130
+ successForeground: success[50],
131
+ warning: warning[600],
132
+ warningForeground: warning[50],
133
+ error: error[600],
134
+ errorForeground: error[50],
135
+ info: info[600],
136
+ infoForeground: info[50]
137
+ },
138
+ /**
139
+ * High-level color schemes for `class` dark mode (e.g. `html.light` / `html.dark` or `data-theme`).
140
+ * Use these to drive backgrounds, text, and surfaces instead of raw neutral steps.
141
+ */
142
+ schemes: {
143
+ light: {
144
+ background: neutral[0],
145
+ foreground: neutral[900],
146
+ card: neutral[0],
147
+ cardForeground: neutral[900],
148
+ popover: neutral[0],
149
+ popoverForeground: neutral[900],
150
+ primary: brand[600],
151
+ primaryForeground: neutral[0],
152
+ secondary: neutral[100],
153
+ secondaryForeground: neutral[900],
154
+ muted: neutral[100],
155
+ mutedForeground: neutral[600],
156
+ accent: neutral[100],
157
+ accentForeground: neutral[900],
158
+ destructive: error[600],
159
+ destructiveForeground: neutral[0],
160
+ success: success[600],
161
+ successForeground: success[50],
162
+ warning: warning[600],
163
+ warningForeground: warning[900],
164
+ error: error[600],
165
+ errorForeground: error[50],
166
+ info: info[600],
167
+ infoForeground: info[50],
168
+ border: neutral[200],
169
+ input: neutral[200],
170
+ ring: brand[500]
171
+ },
172
+ dark: {
173
+ background: neutral[950],
174
+ foreground: neutral[50],
175
+ card: neutral[900],
176
+ cardForeground: neutral[50],
177
+ popover: neutral[900],
178
+ popoverForeground: neutral[50],
179
+ primary: brand[500],
180
+ primaryForeground: neutral[950],
181
+ secondary: neutral[800],
182
+ secondaryForeground: neutral[50],
183
+ muted: neutral[800],
184
+ mutedForeground: neutral[400],
185
+ accent: neutral[800],
186
+ accentForeground: neutral[50],
187
+ destructive: error[500],
188
+ destructiveForeground: neutral[0],
189
+ success: success[500],
190
+ successForeground: neutral[950],
191
+ warning: warning[500],
192
+ warningForeground: neutral[950],
193
+ error: error[500],
194
+ errorForeground: neutral[950],
195
+ info: info[500],
196
+ infoForeground: neutral[950],
197
+ border: neutral[800],
198
+ input: neutral[800],
199
+ ring: brand[400]
200
+ }
201
+ }
202
+ };
203
+
204
+ // source/tokens/motion.ts
205
+ var transitionDuration = {
206
+ instant: "0ms",
207
+ fast: "100ms",
208
+ base: "150ms",
209
+ slow: "300ms",
210
+ slower: "500ms"
211
+ };
212
+ var transitionTimingFunction = {
213
+ ease: "cubic-bezier(0.4, 0, 0.2, 1)",
214
+ easeIn: "cubic-bezier(0.4, 0, 1, 1)",
215
+ easeOut: "cubic-bezier(0, 0, 0.2, 1)",
216
+ easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
217
+ spring: "cubic-bezier(0.34, 1.56, 0.64, 1)"
218
+ };
219
+
220
+ // source/tokens/radii.ts
221
+ var borderRadius = {
222
+ none: "0",
223
+ sm: "0.125rem",
224
+ // 2px
225
+ base: "0.25rem",
226
+ // 4px
227
+ md: "0.375rem",
228
+ // 6px
229
+ lg: "0.5rem",
230
+ // 8px
231
+ xl: "0.75rem",
232
+ // 12px
233
+ "2xl": "1rem",
234
+ // 16px
235
+ "3xl": "1.5rem",
236
+ // 24px
237
+ full: "9999px"
238
+ };
239
+
240
+ // source/tokens/shadows.ts
241
+ var boxShadow = {
242
+ none: "none",
243
+ sm: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
244
+ base: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
245
+ md: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
246
+ lg: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
247
+ xl: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
248
+ "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
249
+ inner: "inset 0 2px 4px 0 rgb(0 0 0 / 0.05)"
250
+ };
251
+
252
+ // source/tokens/spacing.ts
253
+ var spacing = {
254
+ px: "1px",
255
+ 0: "0px",
256
+ 0.5: "2px",
257
+ 1: "4px",
258
+ 1.5: "6px",
259
+ 2: "8px",
260
+ 2.5: "10px",
261
+ 3: "12px",
262
+ 3.5: "14px",
263
+ 4: "16px",
264
+ 5: "20px",
265
+ 6: "24px",
266
+ 7: "28px",
267
+ 8: "32px",
268
+ 9: "36px",
269
+ 10: "40px",
270
+ 12: "48px",
271
+ 14: "56px",
272
+ 16: "64px",
273
+ 20: "80px",
274
+ 24: "96px",
275
+ 32: "128px",
276
+ 40: "160px",
277
+ 48: "192px",
278
+ 64: "256px"
279
+ };
280
+
281
+ // source/tokens/typography.ts
282
+ var typography = {
283
+ fontFamily: {
284
+ sans: ["Inter Variable", "Inter", "system-ui", "sans-serif"],
285
+ mono: ["JetBrains Mono", "Fira Code", "monospace"],
286
+ display: ["Cal Sans", "Inter Variable", "sans-serif"]
287
+ },
288
+ fontSize: {
289
+ "2xs": ["0.625rem", { lineHeight: "0.875rem" }],
290
+ xs: ["0.75rem", { lineHeight: "1rem" }],
291
+ sm: ["0.875rem", { lineHeight: "1.25rem" }],
292
+ base: ["1rem", { lineHeight: "1.5rem" }],
293
+ lg: ["1.125rem", { lineHeight: "1.75rem" }],
294
+ xl: ["1.25rem", { lineHeight: "1.75rem" }],
295
+ "2xl": ["1.5rem", { lineHeight: "2rem" }],
296
+ "3xl": ["1.875rem", { lineHeight: "2.25rem" }],
297
+ "4xl": ["2.25rem", { lineHeight: "2.5rem" }],
298
+ "5xl": ["3rem", { lineHeight: "1" }]
299
+ },
300
+ fontWeight: {
301
+ regular: "400",
302
+ medium: "500",
303
+ semibold: "600",
304
+ bold: "700"
305
+ }
306
+ };
307
+
308
+ export {
309
+ breakpoints,
310
+ colors,
311
+ transitionDuration,
312
+ transitionTimingFunction,
313
+ borderRadius,
314
+ boxShadow,
315
+ spacing,
316
+ typography
317
+ };