@nordmanai/nif 0.2.10 → 0.2.12
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/index.js +273 -260
- package/dist/styles.css +1 -1
- package/dist/ui/components/nm-form-field/nm-form-field.d.ts +12 -2
- package/dist/ui/components/nm-sidebar/nm-sidebar.d.ts +8 -2
- package/package.json +1 -1
- package/registry/index.json +1 -1
- package/registry/ui/components/nm-form-field/nm-form-field.css +22 -0
- package/registry/ui/components/nm-form-field/nm-form-field.tsx +28 -3
- package/registry/ui/components/nm-sidebar/nm-sidebar.css +2 -1
- package/registry/ui/components/nm-sidebar/nm-sidebar.tsx +22 -3
- package/registry/ui/styles/tokens.css +4 -0
|
@@ -4,11 +4,21 @@ export declare function NmFieldSet({ className, ...props }: ComponentProps<'fiel
|
|
|
4
4
|
export declare function NmFieldLegend({ className, variant, ...props }: ComponentProps<'legend'> & {
|
|
5
5
|
variant?: 'legend' | 'label';
|
|
6
6
|
}): import("react").JSX.Element;
|
|
7
|
-
export
|
|
8
|
-
|
|
7
|
+
export type NmFieldGroupColumns = 1 | 2 | 3;
|
|
8
|
+
/**
|
|
9
|
+
* A group stacks by default. With columns, it lays fields out in a grid of up to two or three
|
|
10
|
+
* columns, falling back to fewer when the container is narrow so long pages stay short on wide
|
|
11
|
+
* screens without getting cramped on small ones. A child with span="full" takes the whole row.
|
|
12
|
+
*/
|
|
13
|
+
export declare function NmFieldGroup({ className, columns, ...props }: ComponentProps<'div'> & {
|
|
14
|
+
columns?: NmFieldGroupColumns;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
16
|
+
export declare function NmFormField({ className, orientation, invalid, disabled, span, ...props }: ComponentProps<'div'> & {
|
|
9
17
|
orientation?: 'vertical' | 'horizontal';
|
|
10
18
|
invalid?: boolean;
|
|
11
19
|
disabled?: boolean;
|
|
20
|
+
/** Inside a multi-column group: take the whole row. */
|
|
21
|
+
span?: 'full';
|
|
12
22
|
}): import("react").JSX.Element;
|
|
13
23
|
export declare function NmFieldContent({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
14
24
|
export declare function NmFieldLabel({ className, ...props }: ComponentProps<'label'>): import("react").JSX.Element;
|
|
@@ -30,6 +30,8 @@ type SidebarContextValue = {
|
|
|
30
30
|
setCollapsible: (mode: NmSidebarCollapsible) => void;
|
|
31
31
|
};
|
|
32
32
|
/** The sidebar's state: expanded or collapsed, peeking, on a desktop or a phone, and the function that toggles it. */
|
|
33
|
+
/** The sidebar context when there is one. For a part that lives in a bar shared by pages with and without a sidebar. */
|
|
34
|
+
export declare function useOptionalSidebar(): SidebarContextValue | null;
|
|
33
35
|
export declare function useSidebar(): SidebarContextValue;
|
|
34
36
|
export type NmSidebarProviderProps = ComponentProps<'div'> & {
|
|
35
37
|
defaultOpen?: boolean;
|
|
@@ -73,7 +75,9 @@ export declare function NmSidebarRail({ className, label, ...props }: ComponentP
|
|
|
73
75
|
label?: string;
|
|
74
76
|
}): ReactNode;
|
|
75
77
|
/** The main area beside the sidebar. With the inset variant it is the raised card. */
|
|
76
|
-
export declare function NmSidebarInset({ className, ...props }: ComponentProps<'main'>
|
|
78
|
+
export declare function NmSidebarInset({ className, render, ref, ...props }: ComponentProps<'main'> & {
|
|
79
|
+
render?: RenderProp;
|
|
80
|
+
}): ReactNode;
|
|
77
81
|
/** A search field in the sidebar. The NIF Input. */
|
|
78
82
|
export declare function NmSidebarInput({ className, ...props }: ComponentProps<typeof NmInput>): ReactNode;
|
|
79
83
|
/** Sticky at the top: a brand, a title or a workspace switcher, and the toggle when the sidebar collapses to it. */
|
|
@@ -122,10 +126,12 @@ export declare function NmSidebarMenuSkeleton({ className, showIcon, ...props }:
|
|
|
122
126
|
/** Rows under a row, indented by a line. */
|
|
123
127
|
export declare function NmSidebarMenuSub({ className, ...props }: ComponentProps<'ul'>): ReactNode;
|
|
124
128
|
export declare function NmSidebarMenuSubItem({ className, ...props }: ComponentProps<'li'>): ReactNode;
|
|
125
|
-
export declare function NmSidebarMenuSubButton({ render, size, isActive, className, ref, ...props }: ComponentProps<'a'> & {
|
|
129
|
+
export declare function NmSidebarMenuSubButton({ render, size, isActive, disabled, className, ref, ...props }: ComponentProps<'a'> & {
|
|
126
130
|
render?: RenderProp;
|
|
127
131
|
size?: Exclude<NmSidebarButtonSize, 'lg'>;
|
|
128
132
|
isActive?: boolean;
|
|
133
|
+
/** Not available. A link gets aria-disabled; a rendered button gets disabled. */
|
|
134
|
+
disabled?: boolean;
|
|
129
135
|
}): ReactNode;
|
|
130
136
|
/** A chevron at the end of a row. In a collapsible row it points right and turns down when the row is open. With `menu` it points down, for a row that opens a menu. */
|
|
131
137
|
export declare function NmSidebarChevron({ className, menu, ...props }: Omit<ComponentProps<typeof NmIcon>, 'id'> & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nordmanai/nif",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "Nordman Interface Framework: the one UI and UX system for every Nordman product. Base UI, in the shadcn composition, styled by NIF tokens.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
package/registry/index.json
CHANGED
|
@@ -27,6 +27,28 @@
|
|
|
27
27
|
gap: var(--nm-space-24);
|
|
28
28
|
width: 100%;
|
|
29
29
|
}
|
|
30
|
+
/* Columns: a cell is never narrower than --nm-width-field-min, so the count drops as the
|
|
31
|
+
container narrows and reaches one column on small screens. */
|
|
32
|
+
.nm-field-group[data-columns] {
|
|
33
|
+
display: grid;
|
|
34
|
+
gap: var(--nm-space-24) var(--nm-space-16);
|
|
35
|
+
align-items: start;
|
|
36
|
+
}
|
|
37
|
+
.nm-field-group[data-columns='2'] {
|
|
38
|
+
grid-template-columns: repeat(
|
|
39
|
+
auto-fit,
|
|
40
|
+
minmax(min(100%, max(var(--nm-width-field-min), calc(var(--nm-field-col-2) - var(--nm-space-16)))), 1fr)
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
.nm-field-group[data-columns='3'] {
|
|
44
|
+
grid-template-columns: repeat(
|
|
45
|
+
auto-fit,
|
|
46
|
+
minmax(min(100%, max(var(--nm-width-field-min), calc(var(--nm-field-col-3) - var(--nm-space-16)))), 1fr)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
.nm-field-group[data-columns] > [data-span='full'] {
|
|
50
|
+
grid-column: 1 / -1;
|
|
51
|
+
}
|
|
30
52
|
|
|
31
53
|
.nm-form-field {
|
|
32
54
|
display: flex;
|
|
@@ -11,8 +11,25 @@ export function NmFieldLegend({ className, variant = 'legend', ...props }: Compo
|
|
|
11
11
|
return <legend data-slot="field-legend" data-variant={variant} className={nmClass('nm-field-legend', className)} {...props} />;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export
|
|
15
|
-
|
|
14
|
+
export type NmFieldGroupColumns = 1 | 2 | 3;
|
|
15
|
+
/**
|
|
16
|
+
* A group stacks by default. With columns, it lays fields out in a grid of up to two or three
|
|
17
|
+
* columns, falling back to fewer when the container is narrow so long pages stay short on wide
|
|
18
|
+
* screens without getting cramped on small ones. A child with span="full" takes the whole row.
|
|
19
|
+
*/
|
|
20
|
+
export function NmFieldGroup({
|
|
21
|
+
className,
|
|
22
|
+
columns = 1,
|
|
23
|
+
...props
|
|
24
|
+
}: ComponentProps<'div'> & { columns?: NmFieldGroupColumns }) {
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
data-slot="field-group"
|
|
28
|
+
data-columns={columns > 1 ? columns : undefined}
|
|
29
|
+
className={nmClass('nm-field-group', className)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
16
33
|
}
|
|
17
34
|
|
|
18
35
|
export function NmFormField({
|
|
@@ -20,13 +37,21 @@ export function NmFormField({
|
|
|
20
37
|
orientation = 'vertical',
|
|
21
38
|
invalid,
|
|
22
39
|
disabled,
|
|
40
|
+
span,
|
|
23
41
|
...props
|
|
24
|
-
}: ComponentProps<'div'> & {
|
|
42
|
+
}: ComponentProps<'div'> & {
|
|
43
|
+
orientation?: 'vertical' | 'horizontal';
|
|
44
|
+
invalid?: boolean;
|
|
45
|
+
disabled?: boolean;
|
|
46
|
+
/** Inside a multi-column group: take the whole row. */
|
|
47
|
+
span?: 'full';
|
|
48
|
+
}) {
|
|
25
49
|
return (
|
|
26
50
|
<div
|
|
27
51
|
data-slot="field"
|
|
28
52
|
role="group"
|
|
29
53
|
data-orientation={orientation}
|
|
54
|
+
data-span={span}
|
|
30
55
|
data-invalid={invalid ? '' : undefined}
|
|
31
56
|
data-disabled={disabled ? '' : undefined}
|
|
32
57
|
className={nmClass('nm-form-field', className)}
|
|
@@ -80,7 +80,8 @@
|
|
|
80
80
|
The column keeps its collapsed width in the flow, and the inner panel floats out over the page. */
|
|
81
81
|
.nm-sidebar[data-peek] {
|
|
82
82
|
overflow: visible;
|
|
83
|
-
|
|
83
|
+
/* Over the main area and its top bar, under menus. */
|
|
84
|
+
z-index: var(--nm-rail-z);
|
|
84
85
|
}
|
|
85
86
|
.nm-sidebar[data-mode='offcanvas'][data-peek] {
|
|
86
87
|
width: 0;
|
|
@@ -63,6 +63,10 @@ const SidebarContext = createContext<SidebarContextValue | null>(null);
|
|
|
63
63
|
const PEEK_KEEPS = '[data-slot="sidebar"], [data-slot="sidebar-trigger"], [data-slot="tooltip-content"], [role="menu"], [role="dialog"]';
|
|
64
64
|
|
|
65
65
|
/** The sidebar's state: expanded or collapsed, peeking, on a desktop or a phone, and the function that toggles it. */
|
|
66
|
+
/** The sidebar context when there is one. For a part that lives in a bar shared by pages with and without a sidebar. */
|
|
67
|
+
export function useOptionalSidebar(): SidebarContextValue | null {
|
|
68
|
+
return useContext(SidebarContext);
|
|
69
|
+
}
|
|
66
70
|
export function useSidebar(): SidebarContextValue {
|
|
67
71
|
const context = useContext(SidebarContext);
|
|
68
72
|
if (!context) {
|
|
@@ -345,8 +349,13 @@ export function NmSidebarRail({ className, label = 'Toggle sidebar', ...props }:
|
|
|
345
349
|
}
|
|
346
350
|
|
|
347
351
|
/** The main area beside the sidebar. With the inset variant it is the raised card. */
|
|
348
|
-
export function NmSidebarInset({ className, ...props }: ComponentProps<'main'>): ReactNode {
|
|
349
|
-
return
|
|
352
|
+
export function NmSidebarInset({ className, render, ref, ...props }: ComponentProps<'main'> & { render?: RenderProp }): ReactNode {
|
|
353
|
+
return useRender({
|
|
354
|
+
render,
|
|
355
|
+
ref,
|
|
356
|
+
defaultTagName: 'main',
|
|
357
|
+
props: { 'data-slot': 'sidebar-inset', className: nmClass('nm-sidebar__inset', className), ...props },
|
|
358
|
+
});
|
|
350
359
|
}
|
|
351
360
|
|
|
352
361
|
/** A search field in the sidebar. The NIF Input. */
|
|
@@ -507,10 +516,17 @@ export function NmSidebarMenuSubButton({
|
|
|
507
516
|
render,
|
|
508
517
|
size = 'default',
|
|
509
518
|
isActive = false,
|
|
519
|
+
disabled = false,
|
|
510
520
|
className,
|
|
511
521
|
ref,
|
|
512
522
|
...props
|
|
513
|
-
}: ComponentProps<'a'> & {
|
|
523
|
+
}: ComponentProps<'a'> & {
|
|
524
|
+
render?: RenderProp;
|
|
525
|
+
size?: Exclude<NmSidebarButtonSize, 'lg'>;
|
|
526
|
+
isActive?: boolean;
|
|
527
|
+
/** Not available. A link gets aria-disabled; a rendered button gets disabled. */
|
|
528
|
+
disabled?: boolean;
|
|
529
|
+
}): ReactNode {
|
|
514
530
|
return useRender({
|
|
515
531
|
render,
|
|
516
532
|
ref,
|
|
@@ -519,6 +535,9 @@ export function NmSidebarMenuSubButton({
|
|
|
519
535
|
'data-slot': 'sidebar-menu-sub-button',
|
|
520
536
|
'data-size': size,
|
|
521
537
|
'data-active': isActive ? '' : undefined,
|
|
538
|
+
'data-disabled': disabled ? '' : undefined,
|
|
539
|
+
'aria-disabled': disabled ? true : undefined,
|
|
540
|
+
disabled: disabled ? true : undefined,
|
|
522
541
|
'aria-current': isActive ? 'page' : undefined,
|
|
523
542
|
className: nmClass('nm-sidebar__menu-sub-button', className),
|
|
524
543
|
...props,
|
|
@@ -274,6 +274,10 @@
|
|
|
274
274
|
--nm-width-popup: 18rem;
|
|
275
275
|
--nm-width-tooltip: 20rem;
|
|
276
276
|
--nm-width-form: 28rem;
|
|
277
|
+
/* Field grids: the narrowest a field cell may be, and the share of the row per column. */
|
|
278
|
+
--nm-width-field-min: 14rem;
|
|
279
|
+
--nm-field-col-2: 50%;
|
|
280
|
+
--nm-field-col-3: 33.333%;
|
|
277
281
|
--nm-code-gutter: 3ch;
|
|
278
282
|
--nm-width-date: 11rem;
|
|
279
283
|
--nm-width-dialog: 40rem;
|