najm-kit 0.0.19 → 0.0.21

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/json.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import * as React2 from 'react';
2
- import React2__default, { createContext, useContext, useMemo, useRef, useCallback } from 'react';
1
+ import * as React3 from 'react';
2
+ import React3__default, { createContext, useContext, useMemo, useRef, useCallback } from 'react';
3
3
  import CodeMirror from '@uiw/react-codemirror';
4
4
  import { json } from '@codemirror/lang-json';
5
5
  import { keymap, EditorView, Decoration, ViewPlugin } from '@codemirror/view';
@@ -173,43 +173,10 @@ function JsonViewer({ value, colors = defaultJsonViewColors, className, maxHeigh
173
173
  }
174
174
  );
175
175
  }
176
- React2.createContext(0);
177
- React2.createContext(null);
178
- var DEFAULT_APPEARANCE = {
179
- borderDegree: "default"
180
- };
181
- var NajmAppearanceContext = React2.createContext(DEFAULT_APPEARANCE);
182
- function useNajmAppearance() {
183
- return React2.useContext(NajmAppearanceContext);
184
- }
185
176
 
186
177
  // src/theme/borders.ts
187
- function resolveBorderDegree(borderDegree, bordered, globalBorderDegree, fallback = "default") {
188
- if (borderDegree) return borderDegree;
189
- if (bordered === true) return "strong";
190
- if (bordered === false) return fallback;
191
- return globalBorderDegree ?? fallback;
192
- }
193
- function borderColorClassForDegree(degree) {
194
- switch (degree) {
195
- case "none":
196
- return "border-transparent";
197
- case "subtle":
198
- return "border-border-subtle";
199
- case "strong":
200
- return "border-border-strong";
201
- default:
202
- return "border-border";
203
- }
204
- }
205
- function useResolvedBorderDegree(options = {}) {
206
- const appearance = useNajmAppearance();
207
- return resolveBorderDegree(
208
- options.borderDegree,
209
- options.bordered,
210
- appearance.borderDegree,
211
- options.fallback
212
- );
178
+ function inputBorderClasses(bordered = true) {
179
+ return bordered === false ? "border-0" : "najm-border border-input";
213
180
  }
214
181
  function toPascalCase(value) {
215
182
  return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[\s_-]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
@@ -234,8 +201,8 @@ var NIcon = ({
234
201
  height: size,
235
202
  ...style
236
203
  };
237
- if (React2__default.isValidElement(icon)) {
238
- return React2__default.cloneElement(icon, {
204
+ if (React3__default.isValidElement(icon)) {
205
+ return React3__default.cloneElement(icon, {
239
206
  className: cn(className, icon.props.className),
240
207
  onClick,
241
208
  ...rest
@@ -282,6 +249,112 @@ var NIcon = ({
282
249
  return null;
283
250
  };
284
251
  NIcon.displayName = "NIcon";
252
+ React3.createContext(0);
253
+ React3.createContext(null);
254
+ var DEFAULT_APPEARANCE = {};
255
+ React3.createContext(DEFAULT_APPEARANCE);
256
+ var NajmDesignContext = React3.createContext({
257
+ components: {}
258
+ });
259
+ function useNajmDesign() {
260
+ return React3.useContext(NajmDesignContext);
261
+ }
262
+ function useNajmComponentStyle(name) {
263
+ const { components } = useNajmDesign();
264
+ return components[name];
265
+ }
266
+
267
+ // src/theme/design-types.ts
268
+ var NAJM_COMPONENT_NAMES = [
269
+ "button",
270
+ "badge",
271
+ "card",
272
+ "table",
273
+ "tabs",
274
+ "dialog",
275
+ "alert",
276
+ "sidebar",
277
+ "pageHeader",
278
+ "input",
279
+ "select",
280
+ "sheet",
281
+ "popover",
282
+ "tooltip",
283
+ "progress",
284
+ "avatar"
285
+ ];
286
+ var RADIUS_VALUE_MAP = {
287
+ none: "0",
288
+ xs: "var(--radius-xs)",
289
+ sm: "var(--radius-sm)",
290
+ md: "var(--radius-md)",
291
+ lg: "var(--radius-lg)",
292
+ xl: "var(--radius-xl)",
293
+ full: "9999px"
294
+ };
295
+ function resolveRadiusValue(radius) {
296
+ if (!radius || radius === "inherit") return void 0;
297
+ return RADIUS_VALUE_MAP[radius] ?? radius;
298
+ }
299
+
300
+ // src/theme/config.ts
301
+ var MODES = ["light", "dark"];
302
+ var TOKEN_KEYS = [
303
+ "background",
304
+ "foreground",
305
+ "card",
306
+ "card-foreground",
307
+ "popover",
308
+ "popover-foreground",
309
+ "primary",
310
+ "primary-foreground",
311
+ "secondary",
312
+ "secondary-foreground",
313
+ "tertiary",
314
+ "tertiary-foreground",
315
+ "muted",
316
+ "muted-foreground",
317
+ "accent",
318
+ "accent-foreground",
319
+ "destructive",
320
+ "destructive-foreground",
321
+ "border",
322
+ "input",
323
+ "ring",
324
+ "sidebar",
325
+ "sidebar-foreground",
326
+ "sidebar-primary",
327
+ "sidebar-primary-foreground",
328
+ "sidebar-accent",
329
+ "sidebar-accent-foreground",
330
+ "sidebar-border",
331
+ "sidebar-ring",
332
+ "chart-1",
333
+ "chart-2",
334
+ "chart-3",
335
+ "chart-4",
336
+ "chart-5",
337
+ "radius"
338
+ ];
339
+ new Set(TOKEN_KEYS);
340
+ new Set(MODES);
341
+
342
+ // src/theme/design-config.ts
343
+ new Set(NAJM_COMPONENT_NAMES);
344
+ function resolveVariantAlias(variants, variant) {
345
+ if (!variants) return { variant };
346
+ const seen = /* @__PURE__ */ new Set();
347
+ let current = variant;
348
+ let style = variants[current];
349
+ while (style?.use && !seen.has(current)) {
350
+ seen.add(current);
351
+ const next = style.use;
352
+ if (seen.has(next)) break;
353
+ current = next;
354
+ style = variants[current];
355
+ }
356
+ return { variant: current, style };
357
+ }
285
358
  var buttonVariants = cva(
286
359
  [
287
360
  "relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-medium outline-none transition-all",
@@ -353,7 +426,7 @@ function renderIcon(icon) {
353
426
  if (!icon) return null;
354
427
  return /* @__PURE__ */ jsx(NIcon, { "aria-hidden": "true", icon, className: "shrink-0" });
355
428
  }
356
- var Button = React2.forwardRef(
429
+ var Button = React3.forwardRef(
357
430
  ({
358
431
  className,
359
432
  variant,
@@ -370,22 +443,26 @@ var Button = React2.forwardRef(
370
443
  leftIcon,
371
444
  rightIcon,
372
445
  bordered,
373
- borderDegree,
374
446
  disabled,
375
447
  children,
376
448
  onClick,
449
+ style,
377
450
  ...props
378
451
  }, ref) => {
379
- const [pending, setPending] = React2.useState(false);
452
+ const recipe = useNajmComponentStyle("button");
453
+ const aliased = resolveVariantAlias(
454
+ recipe?.variants,
455
+ variant ?? recipe?.defaultVariant ?? "default"
456
+ );
457
+ const effVariant = variant ?? aliased.variant ?? recipe?.defaultVariant;
458
+ const effSize = size ?? recipe?.defaultSize;
459
+ const recipeRadius = rounded === void 0 ? resolveRadiusValue(recipe?.radius) : void 0;
460
+ const recipeStyle = recipeRadius ? { borderRadius: recipeRadius } : void 0;
461
+ const [pending, setPending] = React3.useState(false);
380
462
  const isLoading = loading || pending;
381
463
  const isDisabled = disabled || disabledWhileLoading && isLoading;
382
464
  const Comp = asChild ? Slot : "button";
383
- const resolvedBorderDegree = useResolvedBorderDegree({
384
- borderDegree,
385
- bordered,
386
- fallback: "default"
387
- });
388
- const handleClick = React2.useCallback(
465
+ const handleClick = React3.useCallback(
389
466
  (event) => {
390
467
  if (isDisabled) {
391
468
  event.preventDefault();
@@ -414,21 +491,22 @@ var Button = React2.forwardRef(
414
491
  "data-slot": "button",
415
492
  "data-loading": isLoading || void 0,
416
493
  "data-disabled": isDisabled || void 0,
417
- "data-border-degree": variant === "outline" || bordered || borderDegree ? resolvedBorderDegree : void 0,
494
+ "data-bordered": effVariant === "outline" ? "true" : bordered === false ? "false" : bordered ? "true" : void 0,
418
495
  "aria-busy": isLoading || void 0,
419
496
  "aria-disabled": asChild && isDisabled ? true : void 0,
420
497
  disabled: !asChild ? isDisabled : void 0,
498
+ style: recipeStyle ? { ...recipeStyle, ...style } : style,
421
499
  className: cn(
422
- buttonVariants({ variant, size, rounded, fullWidth }),
423
- // Outline buttons always have a border; let the resolved degree drive its color.
424
- variant === "outline" && borderColorClassForDegree(resolvedBorderDegree),
500
+ buttonVariants({ variant: effVariant, size: effSize, rounded, fullWidth }),
501
+ aliased.style?.className,
502
+ // Outline buttons always carry an input-style border.
503
+ effVariant === "outline" && inputBorderClasses(true),
425
504
  // Filled/ghost/plain/link/success/warning/info/soft/subtle buttons only get a
426
- // border when the consumer explicitly opts in via `bordered` or `borderDegree`.
427
- // We do NOT honor the global strong mode for these, because it would make every
428
- // filled button look outlined.
429
- variant !== "outline" && (bordered || borderDegree) && cn(
505
+ // border when the consumer explicitly opts in via `bordered`. Global theming
506
+ // should not outline every filled button.
507
+ effVariant !== "outline" && bordered === true && cn(
430
508
  "border",
431
- borderDegree ? borderColorClassForDegree(resolvedBorderDegree) : "border-muted-foreground"
509
+ "border-muted-foreground"
432
510
  ),
433
511
  className
434
512
  ),
package/dist/theme.css CHANGED
@@ -25,6 +25,7 @@
25
25
  @source inline("{sm,md,lg}:{hidden,flex}");
26
26
  @source inline("border-{black,white}");
27
27
  @source inline("border-{gray,slate,zinc,neutral,stone,red,orange,amber,yellow,green,teal,blue,indigo,purple}{,-600}");
28
+ @source inline("najm-border najm-border-t najm-border-r najm-border-b najm-border-l");
28
29
 
29
30
  /* Map Tailwind's color/radius theme to the runtime --* tokens. `inline` so
30
31
  utilities resolve --* at the element (NajmThemeProvider scopes them per
@@ -46,11 +47,17 @@
46
47
  --color-muted-foreground: var(--muted-foreground);
47
48
  --color-accent: var(--accent);
48
49
  --color-accent-foreground: var(--accent-foreground);
50
+ --color-neutral: var(--neutral);
51
+ --color-neutral-foreground: var(--neutral-foreground);
52
+ --color-info: var(--info);
53
+ --color-info-foreground: var(--info-foreground);
54
+ --color-success: var(--success);
55
+ --color-success-foreground: var(--success-foreground);
56
+ --color-warning: var(--warning);
57
+ --color-warning-foreground: var(--warning-foreground);
49
58
  --color-destructive: var(--destructive);
50
59
  --color-destructive-foreground: var(--destructive-foreground);
51
60
  --color-border: var(--border);
52
- --color-border-subtle: var(--border-subtle);
53
- --color-border-strong: var(--border-strong);
54
61
  --color-input: var(--input);
55
62
  --color-ring: var(--ring);
56
63
 
@@ -87,6 +94,42 @@
87
94
  100% { transform: translateX(200%); width: 40%; }
88
95
  }
89
96
 
97
+ /* Typography variables emitted by NajmDesignProvider. */
98
+ [data-najm-design-vars] {
99
+ font-family: var(--font-sans, ui-sans-serif, system-ui, sans-serif);
100
+ font-size: var(--font-size-base, 14px);
101
+ line-height: var(--line-height-base, 1.5);
102
+ letter-spacing: var(--letter-spacing-base, 0);
103
+ --text-xs: calc(var(--font-size-base, 14px) * 0.857142857 * var(--font-scale, 1));
104
+ --text-xs--line-height: var(--line-height-base, 1.5);
105
+ --text-sm: calc(var(--font-size-base, 14px) * var(--font-scale, 1));
106
+ --text-sm--line-height: var(--line-height-base, 1.5);
107
+ --text-base: calc(var(--font-size-base, 14px) * 1.142857143 * var(--font-scale, 1));
108
+ --text-base--line-height: var(--line-height-base, 1.5);
109
+ --text-lg: calc(var(--font-size-base, 14px) * 1.285714286 * var(--font-scale, 1));
110
+ --text-lg--line-height: var(--line-height-base, 1.5);
111
+ --text-xl: calc(var(--font-size-base, 14px) * 1.428571429 * var(--font-scale, 1));
112
+ --text-xl--line-height: var(--line-height-base, 1.5);
113
+ }
114
+
115
+ [data-najm-design-vars] :where(
116
+ h1,
117
+ h2,
118
+ h3,
119
+ h4,
120
+ h5,
121
+ h6,
122
+ [data-slot="card-title"],
123
+ [data-slot="dialog-title"],
124
+ [data-slot="sheet-title"]
125
+ ) {
126
+ font-family: var(--font-heading, var(--font-sans, ui-sans-serif, system-ui, sans-serif));
127
+ }
128
+
129
+ [data-najm-design-vars] :where(code, kbd, pre, samp) {
130
+ font-family: var(--font-mono, ui-monospace, monospace);
131
+ }
132
+
90
133
  /* Default token values (oklch). Override globally via :root / .dark, or per
91
134
  subtree via <NajmThemeProvider>. */
92
135
  :root {
@@ -106,11 +149,17 @@
106
149
  --muted-foreground: oklch(0.5555 0 0);
107
150
  --accent: oklch(0.2747 0.006 286.001);
108
151
  --accent-foreground: oklch(0.9848 0 0);
152
+ --neutral: oklch(0.556 0 0);
153
+ --neutral-foreground: oklch(0.9848 0 0);
154
+ --info: oklch(0.6231 0.1679 254.149);
155
+ --info-foreground: oklch(0.9848 0 0);
156
+ --success: oklch(0.696 0.17 162.48);
157
+ --success-foreground: oklch(0.1445 0 0);
158
+ --warning: oklch(0.769 0.188 70.08);
159
+ --warning-foreground: oklch(0.1445 0 0);
109
160
  --destructive: oklch(0.6368 0.2078 25.326);
110
161
  --destructive-foreground: oklch(0.9848 0 0);
111
162
  --border: oklch(0.9219 0 0);
112
- --border-subtle: oklch(0.9619 0 0);
113
- --border-strong: oklch(0.4184 0 0);
114
163
  --input: oklch(0.9219 0 0);
115
164
  --ring: oklch(0.2228 0.0043 286.044);
116
165
 
@@ -130,6 +179,7 @@
130
179
  --chart-5: oklch(0.769 0.188 70.08);
131
180
 
132
181
  --radius: 0.5rem;
182
+ --border-width: 1px;
133
183
  }
134
184
 
135
185
  .dark {
@@ -149,11 +199,17 @@
149
199
  --muted-foreground: oklch(0.6255 0.0171 285.896);
150
200
  --accent: oklch(0.2313 0.007 285.839);
151
201
  --accent-foreground: oklch(0.9683 0.0014 286.375);
202
+ --neutral: oklch(0.7155 0 0);
203
+ --neutral-foreground: oklch(0.1445 0 0);
204
+ --info: oklch(0.6231 0.1679 254.149);
205
+ --info-foreground: oklch(0.9683 0.0014 286.375);
206
+ --success: oklch(0.696 0.17 162.48);
207
+ --success-foreground: oklch(0.1445 0 0);
208
+ --warning: oklch(0.769 0.188 70.08);
209
+ --warning-foreground: oklch(0.1445 0 0);
152
210
  --destructive: oklch(0.6356 0.2082 25.378);
153
211
  --destructive-foreground: oklch(1 0 0);
154
212
  --border: oklch(0.262 0.0085 285.799);
155
- --border-subtle: oklch(0.2208 0.0065 285.856);
156
- --border-strong: oklch(0.8294 0 0);
157
213
  --input: oklch(0.262 0.0085 285.799);
158
214
  --ring: oklch(0.2228 0.0043 286.044);
159
215
 
@@ -175,8 +231,29 @@
175
231
  --radius: 0.5rem;
176
232
  }
177
233
 
178
- .border-border-strong {
179
- border-color: var(--border-strong) !important;
234
+ .najm-border {
235
+ border-style: solid;
236
+ border-width: var(--border-width);
237
+ }
238
+
239
+ .najm-border-t {
240
+ border-top-style: solid;
241
+ border-top-width: var(--border-width);
242
+ }
243
+
244
+ .najm-border-r {
245
+ border-right-style: solid;
246
+ border-right-width: var(--border-width);
247
+ }
248
+
249
+ .najm-border-b {
250
+ border-bottom-style: solid;
251
+ border-bottom-width: var(--border-width);
252
+ }
253
+
254
+ .najm-border-l {
255
+ border-left-style: solid;
256
+ border-left-width: var(--border-width);
180
257
  }
181
258
 
182
259
  [data-radix-popper-content-wrapper] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-kit",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "type": "module",
5
5
  "description": "Reusable React UI component package for Najm framework",
6
6
  "main": "./dist/index.mjs",
@@ -104,10 +104,12 @@
104
104
  "class-variance-authority": "^0.7",
105
105
  "clsx": "^2",
106
106
  "cmdk": "^1",
107
+ "culori": "^4.0.2",
107
108
  "date-fns": "^4",
108
109
  "lucide-react": "^0.474",
109
110
  "overlayscrollbars": "^2.16.0",
110
111
  "overlayscrollbars-react": "^0.5.6",
112
+ "react-colorful": "^5.7.0",
111
113
  "react-day-picker": "^9",
112
114
  "react-file-icon": "^1.6.0",
113
115
  "react-international-phone": "^4.8.0",
@@ -117,14 +119,15 @@
117
119
  "zustand": "^5"
118
120
  },
119
121
  "devDependencies": {
122
+ "@hookform/resolvers": "^5",
123
+ "@tailwindcss/postcss": "^4",
120
124
  "@testing-library/react": "^16",
121
125
  "@testing-library/user-event": "^14.6.1",
122
- "@hookform/resolvers": "^5",
126
+ "@types/culori": "^4.0.1",
123
127
  "@types/react": "^19",
124
128
  "@types/react-dom": "^19",
125
129
  "@types/react-file-icon": "^1.0.5",
126
130
  "@vitejs/plugin-react": "^4",
127
- "@tailwindcss/postcss": "^4",
128
131
  "happy-dom": "^17",
129
132
  "postcss": "^8",
130
133
  "react-hook-form": "^7",