@nordmanai/nif 0.2.4 → 0.2.8
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.d.ts +5 -0
- package/dist/index.js +7177 -6682
- package/dist/styles.css +1 -1
- package/dist/ui/components/nm-alert-dialog/nm-alert-dialog.d.ts +17 -0
- package/dist/ui/components/nm-dialog/nm-dialog.d.ts +4 -0
- package/dist/ui/components/nm-drawer/nm-drawer.d.ts +18 -0
- package/dist/ui/components/nm-sidebar/nm-sidebar.d.ts +134 -0
- package/dist/ui/components/nm-textarea/nm-textarea.d.ts +1 -1
- package/dist/ui/config/nm-drawer.d.ts +3 -0
- package/dist/ui/config/nm-sidebar.d.ts +29 -0
- package/package.json +1 -1
- package/registry/index.json +258 -18
- package/registry/ui/components/nm-alert-dialog/nm-alert-dialog.css +4 -0
- package/registry/ui/components/nm-alert-dialog/nm-alert-dialog.tsx +43 -0
- package/registry/ui/components/nm-dialog/nm-dialog.css +15 -0
- package/registry/ui/components/nm-dialog/nm-dialog.tsx +8 -0
- package/registry/ui/components/nm-drawer/nm-drawer.css +70 -0
- package/registry/ui/components/nm-drawer/nm-drawer.tsx +41 -0
- package/registry/ui/components/nm-sidebar/nm-sidebar.css +647 -0
- package/registry/ui/components/nm-sidebar/nm-sidebar.tsx +532 -0
- package/registry/ui/components/nm-textarea/nm-textarea.css +25 -97
- package/registry/ui/components/nm-textarea/nm-textarea.tsx +45 -77
- package/registry/ui/config/nm-drawer.ts +3 -0
- package/registry/ui/config/nm-sidebar.ts +37 -0
- package/registry/ui/styles/tokens.css +10 -0
|
@@ -88,43 +88,36 @@
|
|
|
88
88
|
position: fixed;
|
|
89
89
|
inset: 0;
|
|
90
90
|
z-index: var(--nm-menu-z);
|
|
91
|
-
background: rgb(var(--nm-canvas-rgb) / 0.
|
|
92
|
-
backdrop-filter: blur(4px);
|
|
93
|
-
-webkit-backdrop-filter: blur(4px);
|
|
91
|
+
background: rgb(var(--nm-canvas-rgb) / 0.5);
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
.nm-textarea-panel {
|
|
94
|
+
.nm-side-panel.nm-textarea-side-panel {
|
|
97
95
|
position: fixed;
|
|
98
96
|
top: 0;
|
|
99
97
|
right: 0;
|
|
100
98
|
bottom: 0;
|
|
101
99
|
z-index: calc(var(--nm-menu-z) + 1);
|
|
100
|
+
box-sizing: border-box;
|
|
102
101
|
display: flex;
|
|
102
|
+
flex: none;
|
|
103
103
|
flex-direction: column;
|
|
104
|
-
width:
|
|
105
|
-
border-
|
|
106
|
-
background: var(--nm-
|
|
107
|
-
color: var(--nm-fg);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
.nm-textarea-panel__header {
|
|
111
|
-
display: flex;
|
|
112
|
-
align-items: center;
|
|
113
|
-
justify-content: space-between;
|
|
114
|
-
padding: var(--nm-space-12) var(--nm-space-16);
|
|
115
|
-
border-bottom: var(--nm-rule) solid var(--nm-line-strong);
|
|
116
|
-
gap: var(--nm-space-12);
|
|
104
|
+
width: var(--nm-side-panel-basis, 50%);
|
|
105
|
+
border-inline-start: var(--nm-rule) solid var(--nm-divider);
|
|
106
|
+
background: var(--nm-canvas);
|
|
117
107
|
}
|
|
118
108
|
|
|
119
|
-
.nm-textarea-
|
|
109
|
+
.nm-textarea-panel__body {
|
|
110
|
+
flex: 1;
|
|
120
111
|
display: flex;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
min-height: 0;
|
|
114
|
+
padding: var(--nm-space-12);
|
|
115
|
+
overflow: hidden;
|
|
124
116
|
}
|
|
125
117
|
|
|
126
118
|
.nm-textarea-panel__title {
|
|
127
119
|
margin: 0;
|
|
120
|
+
padding-inline-start: var(--nm-space-8);
|
|
128
121
|
font-size: var(--nm-type-ui);
|
|
129
122
|
font-weight: var(--nm-weight-semibold);
|
|
130
123
|
color: var(--nm-fg);
|
|
@@ -133,47 +126,6 @@
|
|
|
133
126
|
text-overflow: ellipsis;
|
|
134
127
|
}
|
|
135
128
|
|
|
136
|
-
.nm-textarea-panel__actions {
|
|
137
|
-
display: flex;
|
|
138
|
-
align-items: center;
|
|
139
|
-
gap: var(--nm-space-4);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.nm-textarea-panel__action-btn {
|
|
143
|
-
display: inline-flex;
|
|
144
|
-
align-items: center;
|
|
145
|
-
justify-content: center;
|
|
146
|
-
width: var(--control-h);
|
|
147
|
-
height: var(--control-h);
|
|
148
|
-
padding: 0;
|
|
149
|
-
border: 0;
|
|
150
|
-
border-radius: var(--nm-control-r);
|
|
151
|
-
background: transparent;
|
|
152
|
-
color: var(--nm-fg-muted);
|
|
153
|
-
cursor: pointer;
|
|
154
|
-
transition: color 0.15s, background-color 0.15s;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.nm-textarea-panel__action-btn:hover {
|
|
158
|
-
background: var(--nm-raised);
|
|
159
|
-
color: var(--nm-fg);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.nm-textarea-panel__action-btn:focus-visible {
|
|
163
|
-
outline: var(--nm-rule) solid var(--nm-fg);
|
|
164
|
-
outline-offset: var(--nm-rule);
|
|
165
|
-
color: var(--nm-fg);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.nm-textarea-panel__body {
|
|
169
|
-
flex: 1;
|
|
170
|
-
display: flex;
|
|
171
|
-
flex-direction: column;
|
|
172
|
-
overflow: auto;
|
|
173
|
-
min-height: 0;
|
|
174
|
-
background: var(--nm-canvas);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
129
|
.nm-textarea-panel__editor {
|
|
178
130
|
box-sizing: border-box;
|
|
179
131
|
flex: 1;
|
|
@@ -181,7 +133,8 @@
|
|
|
181
133
|
height: 100%;
|
|
182
134
|
min-height: 100%;
|
|
183
135
|
padding: var(--nm-space-16);
|
|
184
|
-
border:
|
|
136
|
+
border: var(--nm-rule) solid var(--nm-line-strong);
|
|
137
|
+
border-radius: var(--nm-control-r);
|
|
185
138
|
outline: none;
|
|
186
139
|
resize: none;
|
|
187
140
|
background: var(--nm-raised);
|
|
@@ -192,12 +145,20 @@
|
|
|
192
145
|
line-height: var(--nm-leading-relaxed);
|
|
193
146
|
}
|
|
194
147
|
|
|
148
|
+
.nm-textarea-panel__editor:focus-visible {
|
|
149
|
+
border-color: var(--nm-fg);
|
|
150
|
+
}
|
|
151
|
+
|
|
195
152
|
.nm-textarea-panel__preview {
|
|
196
153
|
box-sizing: border-box;
|
|
197
154
|
flex: 1;
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: 100%;
|
|
198
157
|
padding: var(--nm-space-16);
|
|
199
158
|
overflow-y: auto;
|
|
200
|
-
|
|
159
|
+
border: var(--nm-rule) solid var(--nm-line-strong);
|
|
160
|
+
border-radius: var(--nm-control-r);
|
|
161
|
+
background: var(--nm-raised);
|
|
201
162
|
}
|
|
202
163
|
|
|
203
164
|
.nm-textarea-panel__empty {
|
|
@@ -206,36 +167,3 @@
|
|
|
206
167
|
font-size: var(--nm-type-ui-sm);
|
|
207
168
|
font-style: italic;
|
|
208
169
|
}
|
|
209
|
-
|
|
210
|
-
.nm-textarea-panel__footer {
|
|
211
|
-
display: flex;
|
|
212
|
-
align-items: center;
|
|
213
|
-
justify-content: space-between;
|
|
214
|
-
padding: var(--nm-space-8) var(--nm-space-16);
|
|
215
|
-
border-top: var(--nm-rule) solid var(--nm-line-strong);
|
|
216
|
-
background: var(--nm-panel);
|
|
217
|
-
font-size: var(--nm-type-ui-sm);
|
|
218
|
-
color: var(--nm-fg-subtle);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.nm-textarea-panel__done {
|
|
222
|
-
display: inline-flex;
|
|
223
|
-
align-items: center;
|
|
224
|
-
justify-content: center;
|
|
225
|
-
height: var(--control-h);
|
|
226
|
-
padding: 0 var(--control-px);
|
|
227
|
-
border: var(--nm-rule) solid var(--nm-line-strong);
|
|
228
|
-
border-radius: var(--nm-control-r);
|
|
229
|
-
background: var(--nm-raised);
|
|
230
|
-
color: var(--nm-fg);
|
|
231
|
-
font-family: var(--nm-font);
|
|
232
|
-
font-size: var(--nm-type-ui-sm);
|
|
233
|
-
font-weight: var(--nm-weight-medium);
|
|
234
|
-
cursor: pointer;
|
|
235
|
-
transition: background-color 0.15s, border-color 0.15s;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.nm-textarea-panel__done:hover {
|
|
239
|
-
background: var(--nm-panel);
|
|
240
|
-
border-color: var(--nm-stroke);
|
|
241
|
-
}
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
forwardRef,
|
|
3
3
|
useCallback,
|
|
4
4
|
useEffect,
|
|
5
|
-
useId,
|
|
6
5
|
useRef,
|
|
7
6
|
useState,
|
|
8
7
|
type ChangeEvent,
|
|
@@ -13,7 +12,8 @@ import { createPortal } from 'react-dom';
|
|
|
13
12
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
14
13
|
import { NmIcon } from '../nm-icon/nm-icon.tsx';
|
|
15
14
|
import { NmProse } from '../nm-prose/nm-prose.tsx';
|
|
16
|
-
import {
|
|
15
|
+
import { NmSidePanel, NmSidePanelBody } from '../nm-side-panel/nm-side-panel.tsx';
|
|
16
|
+
import { NmToolbar, NmToolbarButton, NmToolbarSpacer } from '../nm-toolbar/nm-toolbar.tsx';
|
|
17
17
|
import { createLogger } from '../../kit-logger.ts';
|
|
18
18
|
|
|
19
19
|
const logger = createLogger('interface-nm-textarea');
|
|
@@ -25,7 +25,7 @@ export type NmTextareaProps = ComponentProps<'textarea'> & {
|
|
|
25
25
|
openInPanel?: boolean;
|
|
26
26
|
panelTitle?: string;
|
|
27
27
|
panelButtonLabel?: string;
|
|
28
|
-
panelDefaultTab?: 'code' | '
|
|
28
|
+
panelDefaultTab?: 'code' | 'view';
|
|
29
29
|
renderMarkdown?: (markdown: string) => ReactNode;
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -196,11 +196,6 @@ function parseMarkdown(md: string): ReactNode {
|
|
|
196
196
|
return nodes;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
const PANEL_TABS = [
|
|
200
|
-
{ id: 'code', label: 'Code', icon: 'code' as const },
|
|
201
|
-
{ id: 'preview', label: 'Preview', icon: 'presentation' as const },
|
|
202
|
-
] as const;
|
|
203
|
-
|
|
204
199
|
export const NmTextarea = forwardRef<HTMLTextAreaElement, NmTextareaProps>(
|
|
205
200
|
function NmTextarea(
|
|
206
201
|
{
|
|
@@ -220,7 +215,7 @@ export const NmTextarea = forwardRef<HTMLTextAreaElement, NmTextareaProps>(
|
|
|
220
215
|
) {
|
|
221
216
|
const isPanelEnabled = variant === 'panel' || openInPanel;
|
|
222
217
|
const [panelOpen, setPanelOpen] = useState(false);
|
|
223
|
-
const [
|
|
218
|
+
const [view, setView] = useState<'code' | 'view'>(panelDefaultTab);
|
|
224
219
|
const [copied, setCopied] = useState(false);
|
|
225
220
|
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
226
221
|
const internalTextareaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
@@ -277,10 +272,6 @@ export const NmTextarea = forwardRef<HTMLTextAreaElement, NmTextareaProps>(
|
|
|
277
272
|
return () => window.removeEventListener('keydown', onKeyDown);
|
|
278
273
|
}, [panelOpen, handleClose]);
|
|
279
274
|
|
|
280
|
-
const titleId = useId();
|
|
281
|
-
const lineCount = currentValue ? currentValue.split('\n').length : 0;
|
|
282
|
-
const charCount = currentValue.length;
|
|
283
|
-
|
|
284
275
|
const textareaElement = (
|
|
285
276
|
<textarea
|
|
286
277
|
className={nmClass('nm-textarea', className)}
|
|
@@ -312,52 +303,44 @@ export const NmTextarea = forwardRef<HTMLTextAreaElement, NmTextareaProps>(
|
|
|
312
303
|
onClick={handleClose}
|
|
313
304
|
aria-hidden="true"
|
|
314
305
|
/>
|
|
315
|
-
<
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
aria-label={panelTitle ? undefined : 'Markdown Editor'}
|
|
320
|
-
className="nm-textarea-panel"
|
|
306
|
+
<NmSidePanel
|
|
307
|
+
label={panelTitle ?? 'Markdown'}
|
|
308
|
+
open={panelOpen}
|
|
309
|
+
className="nm-textarea-side-panel"
|
|
321
310
|
>
|
|
322
|
-
<
|
|
323
|
-
<
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
onClick={handleClose}
|
|
353
|
-
>
|
|
354
|
-
<NmIcon id="x" />
|
|
355
|
-
</button>
|
|
356
|
-
</div>
|
|
357
|
-
</header>
|
|
311
|
+
<NmToolbar aria-label={panelTitle ?? 'Markdown'}>
|
|
312
|
+
{panelTitle ? <span className="nm-textarea-panel__title">{panelTitle}</span> : null}
|
|
313
|
+
<NmToolbarButton
|
|
314
|
+
icon="code"
|
|
315
|
+
label="Code"
|
|
316
|
+
pressed={view === 'code'}
|
|
317
|
+
tone={view === 'code' ? 'panel' : 'quiet'}
|
|
318
|
+
onClick={() => setView('code')}
|
|
319
|
+
/>
|
|
320
|
+
<NmToolbarButton
|
|
321
|
+
icon="presentation"
|
|
322
|
+
label="View"
|
|
323
|
+
pressed={view === 'view'}
|
|
324
|
+
tone={view === 'view' ? 'panel' : 'quiet'}
|
|
325
|
+
onClick={() => setView('view')}
|
|
326
|
+
/>
|
|
327
|
+
<NmToolbarSpacer />
|
|
328
|
+
<NmToolbarButton
|
|
329
|
+
icon={copied ? 'check' : 'copy'}
|
|
330
|
+
label={copied ? 'Copied' : 'Copy'}
|
|
331
|
+
tone="quiet"
|
|
332
|
+
onClick={handleCopy}
|
|
333
|
+
/>
|
|
334
|
+
<NmToolbarButton
|
|
335
|
+
icon="x"
|
|
336
|
+
label="Close"
|
|
337
|
+
tone="quiet"
|
|
338
|
+
onClick={handleClose}
|
|
339
|
+
/>
|
|
340
|
+
</NmToolbar>
|
|
358
341
|
|
|
359
|
-
<
|
|
360
|
-
{
|
|
342
|
+
<NmSidePanelBody className="nm-textarea-panel__body">
|
|
343
|
+
{view === 'code' ? (
|
|
361
344
|
<textarea
|
|
362
345
|
className="nm-textarea-panel__editor"
|
|
363
346
|
value={currentValue}
|
|
@@ -367,27 +350,12 @@ export const NmTextarea = forwardRef<HTMLTextAreaElement, NmTextareaProps>(
|
|
|
367
350
|
onChange={(e) => handlePanelTextChange(e.target.value)}
|
|
368
351
|
/>
|
|
369
352
|
) : (
|
|
370
|
-
<
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
</NmProse>
|
|
374
|
-
</div>
|
|
353
|
+
<NmProse className="nm-textarea-panel__preview">
|
|
354
|
+
{renderMarkdown ? renderMarkdown(currentValue) : parseMarkdown(currentValue)}
|
|
355
|
+
</NmProse>
|
|
375
356
|
)}
|
|
376
|
-
</
|
|
377
|
-
|
|
378
|
-
<footer className="nm-textarea-panel__footer">
|
|
379
|
-
<span>
|
|
380
|
-
{lineCount} {lineCount === 1 ? 'line' : 'lines'} · {charCount} characters
|
|
381
|
-
</span>
|
|
382
|
-
<button
|
|
383
|
-
type="button"
|
|
384
|
-
className="nm-textarea-panel__done"
|
|
385
|
-
onClick={handleClose}
|
|
386
|
-
>
|
|
387
|
-
Done
|
|
388
|
-
</button>
|
|
389
|
-
</footer>
|
|
390
|
-
</aside>
|
|
357
|
+
</NmSidePanelBody>
|
|
358
|
+
</NmSidePanel>
|
|
391
359
|
</>,
|
|
392
360
|
document.body,
|
|
393
361
|
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Which edge of the view the sidebar sits on. */
|
|
2
|
+
export const NM_SIDEBAR_SIDES = ['left', 'right'] as const;
|
|
3
|
+
export type NmSidebarSide = (typeof NM_SIDEBAR_SIDES)[number];
|
|
4
|
+
|
|
5
|
+
/** `sidebar` is flush with the edge. `floating` is a raised card inside a margin. `inset` sits in a margin and the main area is the raised card. */
|
|
6
|
+
export const NM_SIDEBAR_VARIANTS = ['sidebar', 'floating', 'inset'] as const;
|
|
7
|
+
export type NmSidebarVariant = (typeof NM_SIDEBAR_VARIANTS)[number];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* How the sidebar collapses.
|
|
11
|
+
* `offcanvas` slides out of view; the trigger lives in the main area.
|
|
12
|
+
* `icon` keeps a column of icons, one per row.
|
|
13
|
+
* `toggle` keeps only the toggle button, in the sidebar's own header.
|
|
14
|
+
* `none` never collapses.
|
|
15
|
+
*/
|
|
16
|
+
export const NM_SIDEBAR_COLLAPSIBLE = ['offcanvas', 'icon', 'toggle', 'none'] as const;
|
|
17
|
+
export type NmSidebarCollapsible = (typeof NM_SIDEBAR_COLLAPSIBLE)[number];
|
|
18
|
+
|
|
19
|
+
export const NM_SIDEBAR_STATES = ['expanded', 'collapsed'] as const;
|
|
20
|
+
export type NmSidebarState = (typeof NM_SIDEBAR_STATES)[number];
|
|
21
|
+
|
|
22
|
+
/** Row heights of a menu button: the small, default and large control heights. */
|
|
23
|
+
export const NM_SIDEBAR_BUTTON_SIZES = ['sm', 'default', 'lg'] as const;
|
|
24
|
+
export type NmSidebarButtonSize = (typeof NM_SIDEBAR_BUTTON_SIZES)[number];
|
|
25
|
+
|
|
26
|
+
/** `default` is a quiet row that fills on hover. `outline` draws the row's line and raises it. */
|
|
27
|
+
export const NM_SIDEBAR_BUTTON_VARIANTS = ['default', 'outline'] as const;
|
|
28
|
+
export type NmSidebarButtonVariant = (typeof NM_SIDEBAR_BUTTON_VARIANTS)[number];
|
|
29
|
+
|
|
30
|
+
/** The key that toggles the sidebar with the platform modifier: ⌘B on Mac, Ctrl+B elsewhere. */
|
|
31
|
+
export const NM_SIDEBAR_SHORTCUT = 'b';
|
|
32
|
+
|
|
33
|
+
/** How long the pointer may be between the toggle and the peeked sidebar before the peek closes, in ms. */
|
|
34
|
+
export const NM_SIDEBAR_PEEK_LEAVE_MS = 200;
|
|
35
|
+
|
|
36
|
+
/** Below this width the sidebar opens over the page instead of beside it. The same breakpoint as the tokens' phone step. */
|
|
37
|
+
export const NM_SIDEBAR_MOBILE_QUERY = '(max-width: 48rem)';
|
|
@@ -205,8 +205,17 @@
|
|
|
205
205
|
--nm-width-tile: 9rem;
|
|
206
206
|
--nm-width-panel-min: 16rem;
|
|
207
207
|
--nm-width-panel-max: 80%;
|
|
208
|
+
/* The sidebar beside the main area: open, on a phone, and collapsed to icons (a square row inside the group padding). */
|
|
209
|
+
--nm-width-sidebar: 16rem;
|
|
210
|
+
--nm-width-sidebar-mobile: 18rem;
|
|
211
|
+
/* A drawer over the page from an edge. */
|
|
212
|
+
--nm-width-drawer: 20rem;
|
|
213
|
+
--nm-width-sidebar-icon: calc(var(--control-h) + var(--nm-space-8) * 2);
|
|
208
214
|
--nm-height-workspace-sm: 20rem;
|
|
209
215
|
--nm-height-workspace-lg: 36rem;
|
|
216
|
+
/* A sidebar shown inside a page. */
|
|
217
|
+
--nm-height-sidebar-sm: 26rem;
|
|
218
|
+
--nm-height-sidebar-lg: 42rem;
|
|
210
219
|
/* Typography. Line height, tracking and weight come from here. The typeface itself is in assets/tokens.css. */
|
|
211
220
|
/* Structural dividers and resize handles. Invisible at Contrast 0, and they appear as Contrast rises. */
|
|
212
221
|
--nm-divider: var(--nm-canvas);
|
|
@@ -268,6 +277,7 @@
|
|
|
268
277
|
--nm-code-gutter: 3ch;
|
|
269
278
|
--nm-width-date: 11rem;
|
|
270
279
|
--nm-width-dialog: 40rem;
|
|
280
|
+
--nm-width-alert-dialog: 26rem;
|
|
271
281
|
/* A page column, such as a settings page: a share of the view, never narrower or wider than its bounds. */
|
|
272
282
|
--nm-width-column: 90%;
|
|
273
283
|
--nm-width-column-min: 20rem;
|