najm-kit 0.0.18 → 0.0.20

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,110 @@ 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 TOKEN_KEYS = [
302
+ "background",
303
+ "foreground",
304
+ "card",
305
+ "card-foreground",
306
+ "popover",
307
+ "popover-foreground",
308
+ "primary",
309
+ "primary-foreground",
310
+ "secondary",
311
+ "secondary-foreground",
312
+ "tertiary",
313
+ "tertiary-foreground",
314
+ "muted",
315
+ "muted-foreground",
316
+ "accent",
317
+ "accent-foreground",
318
+ "destructive",
319
+ "destructive-foreground",
320
+ "border",
321
+ "input",
322
+ "ring",
323
+ "sidebar",
324
+ "sidebar-foreground",
325
+ "sidebar-primary",
326
+ "sidebar-primary-foreground",
327
+ "sidebar-accent",
328
+ "sidebar-accent-foreground",
329
+ "sidebar-border",
330
+ "sidebar-ring",
331
+ "chart-1",
332
+ "chart-2",
333
+ "chart-3",
334
+ "chart-4",
335
+ "chart-5",
336
+ "radius"
337
+ ];
338
+ new Set(TOKEN_KEYS);
339
+
340
+ // src/theme/design-config.ts
341
+ new Set(NAJM_COMPONENT_NAMES);
342
+ function resolveVariantAlias(variants, variant) {
343
+ if (!variants) return { variant };
344
+ const seen = /* @__PURE__ */ new Set();
345
+ let current = variant;
346
+ let style = variants[current];
347
+ while (style?.use && !seen.has(current)) {
348
+ seen.add(current);
349
+ const next = style.use;
350
+ if (seen.has(next)) break;
351
+ current = next;
352
+ style = variants[current];
353
+ }
354
+ return { variant: current, style };
355
+ }
285
356
  var buttonVariants = cva(
286
357
  [
287
358
  "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 +424,7 @@ function renderIcon(icon) {
353
424
  if (!icon) return null;
354
425
  return /* @__PURE__ */ jsx(NIcon, { "aria-hidden": "true", icon, className: "shrink-0" });
355
426
  }
356
- var Button = React2.forwardRef(
427
+ var Button = React3.forwardRef(
357
428
  ({
358
429
  className,
359
430
  variant,
@@ -370,22 +441,26 @@ var Button = React2.forwardRef(
370
441
  leftIcon,
371
442
  rightIcon,
372
443
  bordered,
373
- borderDegree,
374
444
  disabled,
375
445
  children,
376
446
  onClick,
447
+ style,
377
448
  ...props
378
449
  }, ref) => {
379
- const [pending, setPending] = React2.useState(false);
450
+ const recipe = useNajmComponentStyle("button");
451
+ const aliased = resolveVariantAlias(
452
+ recipe?.variants,
453
+ variant ?? recipe?.defaultVariant ?? "default"
454
+ );
455
+ const effVariant = variant ?? aliased.variant ?? recipe?.defaultVariant;
456
+ const effSize = size ?? recipe?.defaultSize;
457
+ const recipeRadius = rounded === void 0 ? resolveRadiusValue(recipe?.radius) : void 0;
458
+ const recipeStyle = recipeRadius ? { borderRadius: recipeRadius } : void 0;
459
+ const [pending, setPending] = React3.useState(false);
380
460
  const isLoading = loading || pending;
381
461
  const isDisabled = disabled || disabledWhileLoading && isLoading;
382
462
  const Comp = asChild ? Slot : "button";
383
- const resolvedBorderDegree = useResolvedBorderDegree({
384
- borderDegree,
385
- bordered,
386
- fallback: "default"
387
- });
388
- const handleClick = React2.useCallback(
463
+ const handleClick = React3.useCallback(
389
464
  (event) => {
390
465
  if (isDisabled) {
391
466
  event.preventDefault();
@@ -414,21 +489,22 @@ var Button = React2.forwardRef(
414
489
  "data-slot": "button",
415
490
  "data-loading": isLoading || void 0,
416
491
  "data-disabled": isDisabled || void 0,
417
- "data-border-degree": variant === "outline" || bordered || borderDegree ? resolvedBorderDegree : void 0,
492
+ "data-bordered": effVariant === "outline" ? "true" : bordered === false ? "false" : bordered ? "true" : void 0,
418
493
  "aria-busy": isLoading || void 0,
419
494
  "aria-disabled": asChild && isDisabled ? true : void 0,
420
495
  disabled: !asChild ? isDisabled : void 0,
496
+ style: recipeStyle ? { ...recipeStyle, ...style } : style,
421
497
  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),
498
+ buttonVariants({ variant: effVariant, size: effSize, rounded, fullWidth }),
499
+ aliased.style?.className,
500
+ // Outline buttons always carry an input-style border.
501
+ effVariant === "outline" && inputBorderClasses(true),
425
502
  // 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(
503
+ // border when the consumer explicitly opts in via `bordered`. Global theming
504
+ // should not outline every filled button.
505
+ effVariant !== "outline" && bordered === true && cn(
430
506
  "border",
431
- borderDegree ? borderColorClassForDegree(resolvedBorderDegree) : "border-muted-foreground"
507
+ "border-muted-foreground"
432
508
  ),
433
509
  className
434
510
  ),
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
@@ -49,8 +50,6 @@
49
50
  --color-destructive: var(--destructive);
50
51
  --color-destructive-foreground: var(--destructive-foreground);
51
52
  --color-border: var(--border);
52
- --color-border-subtle: var(--border-subtle);
53
- --color-border-strong: var(--border-strong);
54
53
  --color-input: var(--input);
55
54
  --color-ring: var(--ring);
56
55
 
@@ -109,8 +108,6 @@
109
108
  --destructive: oklch(0.6368 0.2078 25.326);
110
109
  --destructive-foreground: oklch(0.9848 0 0);
111
110
  --border: oklch(0.9219 0 0);
112
- --border-subtle: oklch(0.9619 0 0);
113
- --border-strong: oklch(0.4184 0 0);
114
111
  --input: oklch(0.9219 0 0);
115
112
  --ring: oklch(0.2228 0.0043 286.044);
116
113
 
@@ -130,6 +127,7 @@
130
127
  --chart-5: oklch(0.769 0.188 70.08);
131
128
 
132
129
  --radius: 0.5rem;
130
+ --border-width: 1px;
133
131
  }
134
132
 
135
133
  .dark {
@@ -152,8 +150,6 @@
152
150
  --destructive: oklch(0.6356 0.2082 25.378);
153
151
  --destructive-foreground: oklch(1 0 0);
154
152
  --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
153
  --input: oklch(0.262 0.0085 285.799);
158
154
  --ring: oklch(0.2228 0.0043 286.044);
159
155
 
@@ -175,8 +171,29 @@
175
171
  --radius: 0.5rem;
176
172
  }
177
173
 
178
- .border-border-strong {
179
- border-color: var(--border-strong) !important;
174
+ .najm-border {
175
+ border-style: solid;
176
+ border-width: var(--border-width);
177
+ }
178
+
179
+ .najm-border-t {
180
+ border-top-style: solid;
181
+ border-top-width: var(--border-width);
182
+ }
183
+
184
+ .najm-border-r {
185
+ border-right-style: solid;
186
+ border-right-width: var(--border-width);
187
+ }
188
+
189
+ .najm-border-b {
190
+ border-bottom-style: solid;
191
+ border-bottom-width: var(--border-width);
192
+ }
193
+
194
+ .najm-border-l {
195
+ border-left-style: solid;
196
+ border-left-width: var(--border-width);
180
197
  }
181
198
 
182
199
  [data-radix-popper-content-wrapper] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-kit",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
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",