@simplysm/angular 14.0.23 → 14.0.24
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/package.json +6 -7
- package/README.md +0 -310
- package/docs/core.md +0 -909
- package/docs/features.md +0 -402
- package/docs/styling.md +0 -309
- package/docs/ui-data.md +0 -249
- package/docs/ui-form.md +0 -421
- package/docs/ui-layout.md +0 -216
- package/docs/ui-navigation.md +0 -243
- package/docs/ui-overlay.md +0 -330
- package/docs/ui-visual.md +0 -131
package/docs/features.md
DELETED
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
# Features
|
|
2
|
-
|
|
3
|
-
High-level feature components: address search, base container, data sheet/detail views, and shared-data-backed controls.
|
|
4
|
-
|
|
5
|
-
## `SdAddressSearchModal`
|
|
6
|
-
|
|
7
|
-
Modal component that embeds the Daum Postcode widget for Korean address lookup. Implements `ISdModal<IAddress>`.
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
@Component({ selector: "sd-address-search-modal" })
|
|
11
|
-
class SdAddressSearchModal implements ISdModal<IAddress>, OnInit {
|
|
12
|
-
close = output<IAddress>();
|
|
13
|
-
initialized = signal(false);
|
|
14
|
-
}
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## `IAddress`
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
interface IAddress {
|
|
21
|
-
postNumber: string | undefined;
|
|
22
|
-
address: string | undefined;
|
|
23
|
-
buildingName: string | undefined;
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
| Field | Type | Description |
|
|
28
|
-
|-------|------|-------------|
|
|
29
|
-
| `postNumber` | `string \| undefined` | Postal (zone) code |
|
|
30
|
-
| `address` | `string \| undefined` | Full road/lot address |
|
|
31
|
-
| `buildingName` | `string \| undefined` | Building name |
|
|
32
|
-
|
|
33
|
-
## `SdPermissionTableControl`
|
|
34
|
-
|
|
35
|
-
Matrix table component that displays a hierarchical permission structure with use/edit checkboxes. Groups and leaf items are rendered with depth-based coloring and collapse/expand support.
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
@Component({ selector: "sd-permission-table" })
|
|
39
|
-
class SdPermissionTableControl<TModule> {
|
|
40
|
-
value = model<Record<string, boolean>>({});
|
|
41
|
-
items = input<ISdPermission<TModule>[]>([]);
|
|
42
|
-
disabled = input(false, { transform: booleanAttribute });
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
| Input/Model | Type | Description |
|
|
47
|
-
|-------------|------|-------------|
|
|
48
|
-
| `value` | `Record<string, boolean>` | Two-way binding of permission key-value map (e.g., `{ "admin.users.use": true }`) |
|
|
49
|
-
| `items` | `ISdPermission<TModule>[]` | Hierarchical permission tree from `SdAppStructureProvider` |
|
|
50
|
-
| `disabled` | `boolean` | Disables all checkboxes |
|
|
51
|
-
|
|
52
|
-
Behaviors:
|
|
53
|
-
- Unchecking "use" automatically unchecks "edit" for the same item
|
|
54
|
-
- "edit" checkbox is disabled when "use" is unchecked
|
|
55
|
-
- Checking/unchecking a parent cascades to all children
|
|
56
|
-
- Collapsible groups with depth-based theme coloring (info/warning/success cycle)
|
|
57
|
-
|
|
58
|
-
## `SdBaseContainerControl`
|
|
59
|
-
|
|
60
|
-
Layout shell that wraps a page or modal. Handles busy state, access restriction, and auto-resolves title from app structure or modal context.
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
@Component({ selector: "sd-base-container" })
|
|
64
|
-
class SdBaseContainerControl {
|
|
65
|
-
viewType = input<TSdViewType>();
|
|
66
|
-
header = input<string>();
|
|
67
|
-
initialized = input<boolean | undefined>(undefined);
|
|
68
|
-
restricted = input(false, { transform: booleanAttribute });
|
|
69
|
-
busy = input(false, { transform: booleanAttribute });
|
|
70
|
-
busyMessage = input<string>();
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
| Input | Type | Description |
|
|
75
|
-
|-------|------|-------------|
|
|
76
|
-
| `viewType` | `TSdViewType \| undefined` | Override view type |
|
|
77
|
-
| `header` | `string \| undefined` | Explicit title override |
|
|
78
|
-
| `initialized` | `boolean \| undefined` | Controls rendering gate |
|
|
79
|
-
| `restricted` | `boolean` | Shows "no permission" message |
|
|
80
|
-
| `busy` | `boolean` | Shows busy spinner |
|
|
81
|
-
| `busyMessage` | `string \| undefined` | Message shown during busy |
|
|
82
|
-
|
|
83
|
-
Content templates: `#contentTpl` (required), `#pageTopbarTpl`, `#modalBottomTpl`.
|
|
84
|
-
|
|
85
|
-
## `SdDataSheetControl`
|
|
86
|
-
|
|
87
|
-
Presentation component for data sheet views. Must be placed inside an `AbsSdDataSheet`-extending component. Delegates all logic to the parent.
|
|
88
|
-
|
|
89
|
-
```typescript
|
|
90
|
-
@Component({ selector: "sd-data-sheet" })
|
|
91
|
-
class SdDataSheetControl {
|
|
92
|
-
insertText = input<string>();
|
|
93
|
-
deleteText = input<string>();
|
|
94
|
-
restoreText = input<string>();
|
|
95
|
-
deleteIcon = input(tablerEraser);
|
|
96
|
-
restoreIcon = input(tablerRestore);
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Content templates: `#pageTopbarTpl`, `#prevTpl`, `#filterTpl`, `#beforeToolTpl`, `#toolTpl`, `#modalBottomTpl`. Content children: `SdDataSheetColumnDirective`.
|
|
101
|
-
|
|
102
|
-
## `AbsSdDataSheet`
|
|
103
|
-
|
|
104
|
-
Abstract base directive for data sheet screens. Manages state, change tracking, pagination, sorting, and CRUD.
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
@Directive()
|
|
108
|
-
abstract class AbsSdDataSheet<TFilter, TItem, TKey> {
|
|
109
|
-
// Abstract (must implement)
|
|
110
|
-
abstract canUse: Signal<boolean>;
|
|
111
|
-
abstract canEdit: Signal<boolean>;
|
|
112
|
-
abstract editMode: "inline" | "modal" | undefined;
|
|
113
|
-
abstract selectMode: InputSignal<"single" | "multi" | undefined>;
|
|
114
|
-
abstract itemPropInfo: ISdDataSheetItemPropInfo<TItem>;
|
|
115
|
-
abstract getItemInfoFn: (item: TItem) => ISdDataSheetItemInfo<TKey>;
|
|
116
|
-
abstract bindFilter(): TFilter;
|
|
117
|
-
abstract search(usePagination: boolean): Promise<ISdDataSheetSearchResult<TItem>> | ISdDataSheetSearchResult<TItem>;
|
|
118
|
-
|
|
119
|
-
// Optional abstract
|
|
120
|
-
hideTool?: Signal<boolean>;
|
|
121
|
-
diffsExcludes?: string[];
|
|
122
|
-
prepareRefreshEffect?(): void;
|
|
123
|
-
editItem?(item?: TItem): Promise<boolean | undefined> | boolean | undefined;
|
|
124
|
-
toggleDeleteItems?(del: boolean): Promise<boolean>;
|
|
125
|
-
newItem?(): Promise<TItem> | TItem;
|
|
126
|
-
submit?(diffs: ArrayOneWayDiffResult<TItem>[]): Promise<boolean> | boolean;
|
|
127
|
-
downloadExcel?(items: TItem[]): Promise<void> | void;
|
|
128
|
-
uploadExcel?(file: File): Promise<void> | void;
|
|
129
|
-
|
|
130
|
-
// State
|
|
131
|
-
busyCount = signal(0);
|
|
132
|
-
busyMessage = signal<string | undefined>(undefined);
|
|
133
|
-
initialized = signal(false);
|
|
134
|
-
items = signal<TItem[]>([]);
|
|
135
|
-
selectedItems = signal<TItem[]>([]);
|
|
136
|
-
selectedItemKeys = model<TKey[]>([]);
|
|
137
|
-
summaryData = signal<Partial<TItem>>({});
|
|
138
|
-
page = signal(0);
|
|
139
|
-
pageLength = signal(0);
|
|
140
|
-
sortingDefs = signal<ISortingDef[]>([]);
|
|
141
|
-
filter = signal<TFilter>({} as TFilter);
|
|
142
|
-
lastFilter = signal<TFilter>({} as TFilter);
|
|
143
|
-
|
|
144
|
-
// Output
|
|
145
|
-
close = output<{ selectedItemKeys: TKey[]; selectedItems: TItem[] }>();
|
|
146
|
-
submitted = output<boolean>();
|
|
147
|
-
|
|
148
|
-
// Public methods
|
|
149
|
-
checkIgnoreChanges(): boolean;
|
|
150
|
-
doFilterSubmit(): void;
|
|
151
|
-
doRefresh(): void;
|
|
152
|
-
async refresh(): Promise<void>;
|
|
153
|
-
async doAddItem(): Promise<void>;
|
|
154
|
-
async doSubmit(opt?): Promise<void>;
|
|
155
|
-
doToggleDeleteItem(item: TItem): void;
|
|
156
|
-
async doEditItem(item?: TItem): Promise<void>;
|
|
157
|
-
async doToggleDeleteItems(del: boolean): Promise<void>;
|
|
158
|
-
async doDownloadExcel(): Promise<void>;
|
|
159
|
-
async doUploadExcel(): Promise<void>;
|
|
160
|
-
doModalConfirm(): void;
|
|
161
|
-
doModalCancel(): void;
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
## `ISdDataSheetItemPropInfo`
|
|
166
|
-
|
|
167
|
-
Maps property names for metadata columns.
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
interface ISdDataSheetItemPropInfo<I> {
|
|
171
|
-
isDeleted: (keyof I & string) | undefined;
|
|
172
|
-
lastModifiedAt: (keyof I & string) | undefined;
|
|
173
|
-
lastModifiedBy: (keyof I & string) | undefined;
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
| Field | Type | Description |
|
|
178
|
-
|-------|------|-------------|
|
|
179
|
-
| `isDeleted` | `(keyof I & string) \| undefined` | Property name for soft-delete flag |
|
|
180
|
-
| `lastModifiedAt` | `(keyof I & string) \| undefined` | Property name for last modified timestamp |
|
|
181
|
-
| `lastModifiedBy` | `(keyof I & string) \| undefined` | Property name for last modifier |
|
|
182
|
-
|
|
183
|
-
## `ISdDataSheetItemInfo`
|
|
184
|
-
|
|
185
|
-
Per-item capability flags.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
interface ISdDataSheetItemInfo<K> {
|
|
189
|
-
key: K;
|
|
190
|
-
canSelect: boolean;
|
|
191
|
-
canEdit: boolean;
|
|
192
|
-
canDelete: boolean;
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
| Field | Type | Description |
|
|
197
|
-
|-------|------|-------------|
|
|
198
|
-
| `key` | `K` | Item unique key |
|
|
199
|
-
| `canSelect` | `boolean` | Whether item can be selected |
|
|
200
|
-
| `canEdit` | `boolean` | Whether item can be edited |
|
|
201
|
-
| `canDelete` | `boolean` | Whether item can be deleted |
|
|
202
|
-
|
|
203
|
-
## `ISdDataSheetSearchResult`
|
|
204
|
-
|
|
205
|
-
Return shape of `AbsSdDataSheet.search()`.
|
|
206
|
-
|
|
207
|
-
```typescript
|
|
208
|
-
interface ISdDataSheetSearchResult<I> {
|
|
209
|
-
items: I[];
|
|
210
|
-
pageLength?: number;
|
|
211
|
-
summary?: Partial<I>;
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
| Field | Type | Description |
|
|
216
|
-
|-------|------|-------------|
|
|
217
|
-
| `items` | `I[]` | Result items |
|
|
218
|
-
| `pageLength` | `number \| undefined` | Total page count for pagination |
|
|
219
|
-
| `summary` | `Partial<I> \| undefined` | Optional summary row data |
|
|
220
|
-
|
|
221
|
-
## `SdDataSheetColumnDirective`
|
|
222
|
-
|
|
223
|
-
Extends `SdSheetColumnDirective` with an additional `edit` input for modal edit mode.
|
|
224
|
-
|
|
225
|
-
```typescript
|
|
226
|
-
@Directive({ selector: "sd-data-sheet-column" })
|
|
227
|
-
class SdDataSheetColumnDirective extends SdSheetColumnDirective {
|
|
228
|
-
edit = input(false, { transform: booleanAttribute });
|
|
229
|
-
}
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
## `SdDataDetailControl`
|
|
233
|
-
|
|
234
|
-
Presentation component for detail/form screens. Delegates logic to parent `AbsSdDataDetail`.
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
@Component({ selector: "sd-data-detail" })
|
|
238
|
-
class SdDataDetailControl { }
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
Content templates: `#contentTpl` (required), `#toolTpl`, `#prevTpl`, `#nextTpl`.
|
|
242
|
-
|
|
243
|
-
## `AbsSdDataDetail`
|
|
244
|
-
|
|
245
|
-
Abstract base directive for detail (form) screens. Manages data load, change detection, save, and delete.
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
@Directive()
|
|
249
|
-
abstract class AbsSdDataDetail<T, R = boolean> implements ISdModal<R> {
|
|
250
|
-
// Abstract (must implement)
|
|
251
|
-
abstract canUse: Signal<boolean>;
|
|
252
|
-
abstract canEdit: Signal<boolean>;
|
|
253
|
-
abstract load(): Promise<{ data: T; info: ISdDataDetailDataInfo }> | { data: T; info: ISdDataDetailDataInfo };
|
|
254
|
-
|
|
255
|
-
// Optional abstract
|
|
256
|
-
canDelete?: Signal<boolean>;
|
|
257
|
-
prepareRefreshEffect?(): void;
|
|
258
|
-
toggleDelete?(del: boolean): Promise<R | undefined> | R | undefined;
|
|
259
|
-
submit?(data: T): Promise<R | undefined> | R | undefined;
|
|
260
|
-
|
|
261
|
-
// State
|
|
262
|
-
busyCount = signal(0);
|
|
263
|
-
busyMessage = signal<string | undefined>(undefined);
|
|
264
|
-
initialized = signal(false);
|
|
265
|
-
data = signal<T>({} as T);
|
|
266
|
-
dataInfo = signal<ISdDataDetailDataInfo | undefined>(undefined);
|
|
267
|
-
|
|
268
|
-
// Output
|
|
269
|
-
close = output<R>();
|
|
270
|
-
|
|
271
|
-
// Public methods
|
|
272
|
-
checkIgnoreChanges(): boolean;
|
|
273
|
-
async doRefresh(): Promise<void>;
|
|
274
|
-
async refresh(): Promise<void>;
|
|
275
|
-
async doToggleDelete(del: boolean): Promise<void>;
|
|
276
|
-
async doSubmit(opt?): Promise<void>;
|
|
277
|
-
}
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
## `ISdDataDetailDataInfo`
|
|
281
|
-
|
|
282
|
-
Metadata about the current detail record.
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
interface ISdDataDetailDataInfo {
|
|
286
|
-
isNew: boolean;
|
|
287
|
-
isDeleted: boolean;
|
|
288
|
-
lastModifiedAt: DateTime | undefined;
|
|
289
|
-
lastModifiedBy: string | undefined;
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
| Field | Type | Description |
|
|
294
|
-
|-------|------|-------------|
|
|
295
|
-
| `isNew` | `boolean` | Whether this is a new (unsaved) record |
|
|
296
|
-
| `isDeleted` | `boolean` | Whether this record is soft-deleted |
|
|
297
|
-
| `lastModifiedAt` | `DateTime \| undefined` | Last modification timestamp |
|
|
298
|
-
| `lastModifiedBy` | `string \| undefined` | Last modifier identity |
|
|
299
|
-
|
|
300
|
-
## `SdDataSelectButtonControl`
|
|
301
|
-
|
|
302
|
-
Presentation component for modal-backed select buttons. Delegates to parent `AbsSdDataSelectButton`.
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
@Component({ selector: "sd-data-select-button" })
|
|
306
|
-
class SdDataSelectButtonControl { }
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
Content template: `SdItemOfTemplateDirective` for rendering each selected item.
|
|
310
|
-
|
|
311
|
-
## `AbsSdDataSelectButton`
|
|
312
|
-
|
|
313
|
-
Abstract base directive for select-button components backed by a modal.
|
|
314
|
-
|
|
315
|
-
```typescript
|
|
316
|
-
@Directive()
|
|
317
|
-
abstract class AbsSdDataSelectButton<TItem, TKey> {
|
|
318
|
-
abstract modal: Signal<TSdSelectModalInfo<ISdSelectModal<TKey>>>;
|
|
319
|
-
abstract load(keys: TKey[]): Promise<TItem[]> | TItem[];
|
|
320
|
-
|
|
321
|
-
value = model<TSelectModeValue<TKey>>();
|
|
322
|
-
disabled = input(false, { transform: booleanAttribute });
|
|
323
|
-
required = input(false, { transform: booleanAttribute });
|
|
324
|
-
inset = input(false, { transform: booleanAttribute });
|
|
325
|
-
size = input<"sm" | "lg">();
|
|
326
|
-
selectMode = input<"single" | "multi">("single");
|
|
327
|
-
|
|
328
|
-
selectedItems = signal<TItem[]>([]);
|
|
329
|
-
isNoValue = computed(/* true when value is null/empty */);
|
|
330
|
-
|
|
331
|
-
async doShowModal(options?: ISdModalOptions): Promise<void>;
|
|
332
|
-
doInitialValue(): void;
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
## `SdSharedDataSelectControl`
|
|
337
|
-
|
|
338
|
-
Dropdown select backed by shared data items. Supports single/multi selection, tree hierarchy, search, and modal selection.
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
@Component({ selector: "sd-shared-data-select" })
|
|
342
|
-
class SdSharedDataSelectControl<TItem extends ISharedDataBase<string | number>> {
|
|
343
|
-
value = model<TSelectModeValue<TItem["__valueKey"]>>();
|
|
344
|
-
items = input.required<TItem[]>();
|
|
345
|
-
disabled = input(false, { transform: booleanAttribute });
|
|
346
|
-
required = input(false, { transform: booleanAttribute });
|
|
347
|
-
useUndefined = input(false, { transform: booleanAttribute });
|
|
348
|
-
inset = input(false, { transform: booleanAttribute });
|
|
349
|
-
inline = input(false, { transform: booleanAttribute });
|
|
350
|
-
size = input<"sm" | "lg">();
|
|
351
|
-
selectMode = input<"single" | "multi">("single");
|
|
352
|
-
filterFn = input<(item: TItem, index: number, ...params: any[]) => boolean>();
|
|
353
|
-
filterFnParams = input<any[]>();
|
|
354
|
-
modal = input<TSdSelectModalInfo<any>>();
|
|
355
|
-
editModal = input<ISdModalInfo<ISdModal<boolean>>>();
|
|
356
|
-
selectClass = input<string>();
|
|
357
|
-
multiSelectionDisplayDirection = input<"vertical">();
|
|
358
|
-
getIsHiddenFn = input<(item: TItem, index: number) => boolean>();
|
|
359
|
-
getSearchTextFn = input<(item: TItem, index: number) => string>();
|
|
360
|
-
displayOrderKeyProp = input<string>();
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
Content templates: `SdItemOfTemplateDirective`, `#undefinedTpl`.
|
|
365
|
-
|
|
366
|
-
## `SdSharedDataSelectButtonControl`
|
|
367
|
-
|
|
368
|
-
Concrete `AbsSdDataSelectButton` for shared data with numeric keys.
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
@Component({ selector: "sd-shared-data-select-button" })
|
|
372
|
-
class SdSharedDataSelectButtonControl<TItem extends ISharedDataBase<number>> extends AbsSdDataSelectButton<TItem, number> {
|
|
373
|
-
items = input<TItem[]>([]);
|
|
374
|
-
modal = input.required<TSdSelectModalInfo<ISdSelectModal<any>>>();
|
|
375
|
-
}
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
Content template: `SdItemOfTemplateDirective` (required).
|
|
379
|
-
|
|
380
|
-
## `SdSharedDataSelectListControl`
|
|
381
|
-
|
|
382
|
-
List-style single-selection control for shared data. Supports search, pagination, and modal launch.
|
|
383
|
-
|
|
384
|
-
```typescript
|
|
385
|
-
@Component({ selector: "sd-shared-data-select-list" })
|
|
386
|
-
class SdSharedDataSelectListControl<TItem extends ISharedDataBase<string | number>> {
|
|
387
|
-
selectedItem = model<TItem>();
|
|
388
|
-
canChangeFn = input<(item: TItem | undefined) => boolean | Promise<boolean>>(() => true);
|
|
389
|
-
items = input.required<TItem[]>();
|
|
390
|
-
selectedIcon = input<string>();
|
|
391
|
-
useUndefined = input(false, { transform: booleanAttribute });
|
|
392
|
-
filterFn = input<(item: TItem, index: number) => boolean>();
|
|
393
|
-
modal = input<TSdSelectModalInfo<any>>();
|
|
394
|
-
header = input<string>();
|
|
395
|
-
pageItemCount = input<number>();
|
|
396
|
-
|
|
397
|
-
select(item: TItem | undefined): void;
|
|
398
|
-
toggle(item: TItem | undefined): void;
|
|
399
|
-
}
|
|
400
|
-
```
|
|
401
|
-
|
|
402
|
-
Content templates: `#headerTpl`, `#filterTpl`, `SdItemOfTemplateDirective`, `#undefinedTpl`.
|
package/docs/styling.md
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
# Styling
|
|
2
|
-
|
|
3
|
-
CSS classes, custom properties, themes, and SCSS mixins provided by the `@simplysm/angular` package.
|
|
4
|
-
|
|
5
|
-
## CSS Classes
|
|
6
|
-
|
|
7
|
-
### Flex Layout
|
|
8
|
-
|
|
9
|
-
| Class | Description |
|
|
10
|
-
|-------|-------------|
|
|
11
|
-
| `.flex-row` | `display: flex; flex-direction: row; flex-wrap: nowrap` |
|
|
12
|
-
| `.flex-column` | `display: flex; flex-direction: column; flex-wrap: nowrap` |
|
|
13
|
-
| `.flex-row-inline` | `display: inline-flex; flex-direction: row` |
|
|
14
|
-
| `.flex-column-inline` | `display: inline-flex; flex-direction: column` |
|
|
15
|
-
| `.flex-auto` | `flex: 1 0 auto` — grows but does not shrink |
|
|
16
|
-
| `.flex-fill` | `flex: 1 1 auto; overflow: auto` — fills remaining space |
|
|
17
|
-
| `.flex-min` | `flex: 0 0 0` — collapses to minimum |
|
|
18
|
-
|
|
19
|
-
### Grid Layout
|
|
20
|
-
|
|
21
|
-
| Class | Description |
|
|
22
|
-
|-------|-------------|
|
|
23
|
-
| `.grid` | 12-column CSS grid |
|
|
24
|
-
| `.grid-{1…12}` | Span N columns |
|
|
25
|
-
| `.grid-sm-{1…12}` | Span N columns at ≤1280px |
|
|
26
|
-
| `.grid-xs-{1…12}` | Span N columns at ≤1024px |
|
|
27
|
-
| `.grid-xxs-{1…12}` | Span N columns at ≤800px |
|
|
28
|
-
|
|
29
|
-
### Card
|
|
30
|
-
|
|
31
|
-
| Class | Description |
|
|
32
|
-
|-------|-------------|
|
|
33
|
-
| `.card` | Block with control-color background, border-radius, elevation 2 shadow, entrance animation. Elevation 4 on hover/focus-within |
|
|
34
|
-
|
|
35
|
-
### Font Size
|
|
36
|
-
|
|
37
|
-
| Class | Description |
|
|
38
|
-
|-------|-------------|
|
|
39
|
-
| `.ft-size-{key}` | `font-size: var(--font-size-{key})` — keys: `lg`, `default`, `sm`, `h1`–`h6` |
|
|
40
|
-
|
|
41
|
-
### Background
|
|
42
|
-
|
|
43
|
-
| Class | Description |
|
|
44
|
-
|-------|-------------|
|
|
45
|
-
| `.bg-theme-{theme}-{shade}` | Background from theme color. Themes: `gray`, `blue-gray`, `primary`, `secondary`, `info`, `success`, `warning`, `danger`. Shades: `lightest`–`darkest` |
|
|
46
|
-
| `.bg-trans-{key}` | Translucent black background. Keys: `darkest`–`lightest`, `rev-default`–`rev-lightest` |
|
|
47
|
-
| `.bg-default` | Background color set to `--background-color` |
|
|
48
|
-
| `.bg-control` | Background set to `--control-color` |
|
|
49
|
-
|
|
50
|
-
### Text Color
|
|
51
|
-
|
|
52
|
-
| Class | Description |
|
|
53
|
-
|-------|-------------|
|
|
54
|
-
| `.tx-trans-{key}` | Text color from `--text-trans-{key}`. Keys: `dark`, `default`, `light`, `lighter`, `lightest`, `rev-default`, `rev-dark`, `rev-darker` |
|
|
55
|
-
| `.tx-theme-{theme}-{shade}` | Text color from theme palette |
|
|
56
|
-
| `.tx-line-through` | `text-decoration: line-through` |
|
|
57
|
-
| `.tx-underline` | `text-decoration: underline` |
|
|
58
|
-
| `.tx-left` | `text-align: left` |
|
|
59
|
-
| `.tx-right` | `text-align: right` |
|
|
60
|
-
| `.tx-center` | `text-align: center` |
|
|
61
|
-
|
|
62
|
-
### Border
|
|
63
|
-
|
|
64
|
-
| Class | Description |
|
|
65
|
-
|-------|-------------|
|
|
66
|
-
| `.bd` | `border: 1px solid` |
|
|
67
|
-
| `.bd-theme-{theme}-{shade}` | Border color from theme palette |
|
|
68
|
-
| `.bd-trans-{key}` | Border color from transparent scale |
|
|
69
|
-
| `.bd-color-{key}` | Border color from semantic scale: `lighter`, `light`, `default`, `dark`, `darker` |
|
|
70
|
-
| `.bd-none` | Removes border |
|
|
71
|
-
| `.bd-transparent` | Transparent border-color |
|
|
72
|
-
| `.bd{t\|r\|b\|l}` | Directional border (e.g., `.bdt`, `.bdr`, `.bdb`, `.bdl`) |
|
|
73
|
-
| `.bd{t\|r\|b\|l}-theme-{theme}-{shade}` | Directional border color from theme |
|
|
74
|
-
| `.bd{t\|r\|b\|l}-trans-{key}` | Directional border color from transparent scale |
|
|
75
|
-
| `.bd{t\|r\|b\|l}-color-{key}` | Directional border color from semantic scale |
|
|
76
|
-
| `.bd{t\|r\|b\|l}-none` | Removes directional border |
|
|
77
|
-
| `.bd{t\|r\|b\|l}-transparent` | Transparent directional border |
|
|
78
|
-
|
|
79
|
-
### Border Width
|
|
80
|
-
|
|
81
|
-
| Class | Description |
|
|
82
|
-
|-------|-------------|
|
|
83
|
-
| `.bd-width-{key}` | Border width from gap scale: `xxs`–`xxl`, `0`, `auto` |
|
|
84
|
-
| `.bd{t\|r\|b\|l}-width-{key}` | Directional border width |
|
|
85
|
-
|
|
86
|
-
### Border Radius
|
|
87
|
-
|
|
88
|
-
| Class | Description |
|
|
89
|
-
|-------|-------------|
|
|
90
|
-
| `.bd-radius-{key}` | `border-radius: var(--border-radius-{key})` — keys: `xs`–`xxl` |
|
|
91
|
-
| `.bdt-radius-{key}` | Top-left + top-right radius |
|
|
92
|
-
| `.bdb-radius-{key}` | Bottom-left + bottom-right radius |
|
|
93
|
-
| `.bdl-radius-{key}` | Top-left + bottom-left radius |
|
|
94
|
-
| `.bdr-radius-{key}` | Top-right + bottom-right radius |
|
|
95
|
-
|
|
96
|
-
### Spacing (Padding / Margin / Position)
|
|
97
|
-
|
|
98
|
-
Gap keys: `xxs` (0.0833rem), `xs` (0.1667rem), `sm` (0.3333rem), `default` (0.5rem), `lg` (0.6667rem), `xl` (1rem), `xxl` (1.5rem), `0`, `auto`.
|
|
99
|
-
|
|
100
|
-
| Class | Description |
|
|
101
|
-
|-------|-------------|
|
|
102
|
-
| `.p-{key}` | Padding all sides |
|
|
103
|
-
| `.pv-{key}` | Padding top + bottom |
|
|
104
|
-
| `.ph-{key}` | Padding left + right |
|
|
105
|
-
| `.p{t\|r\|b\|l}-{key}` | Directional padding |
|
|
106
|
-
| `.m-{key}` | Margin all sides |
|
|
107
|
-
| `.mv-{key}` | Margin top + bottom |
|
|
108
|
-
| `.mh-{key}` | Margin left + right |
|
|
109
|
-
| `.m{t\|r\|b\|l}-{key}` | Directional margin |
|
|
110
|
-
| `.{t\|r\|b\|l}-{key}` | Positional offset (top/right/bottom/left) |
|
|
111
|
-
|
|
112
|
-
### Sizing
|
|
113
|
-
|
|
114
|
-
| Class | Description |
|
|
115
|
-
|-------|-------------|
|
|
116
|
-
| `.sw-{key}` | `width: var(--gap-{key})` |
|
|
117
|
-
| `.sh-{key}` | `height: var(--gap-{key})` |
|
|
118
|
-
| `.sh-topbar` | `height: var(--topbar-height)` |
|
|
119
|
-
| `.sw-sidebar` | `width: var(--sidebar-width)` |
|
|
120
|
-
|
|
121
|
-
### Alignment
|
|
122
|
-
|
|
123
|
-
| Class | Description |
|
|
124
|
-
|-------|-------------|
|
|
125
|
-
| `.main-align-{start\|end\|center}` | `justify-content` |
|
|
126
|
-
| `.cross-align-{start\|end\|center}` | `align-items` |
|
|
127
|
-
| `.gap-{key}` | `gap: var(--gap-{key})` |
|
|
128
|
-
|
|
129
|
-
### Form & Table
|
|
130
|
-
|
|
131
|
-
| Class | Description |
|
|
132
|
-
|-------|-------------|
|
|
133
|
-
| `.form-control` | Base form input styling (padding, border, font) |
|
|
134
|
-
| `.form-box` | Vertical flex form layout with labeled children |
|
|
135
|
-
| `.form-box-inline` | Inline-flex row wrap form layout |
|
|
136
|
-
| `.form-box-item` | Child item class for `.form-box` |
|
|
137
|
-
| `.form-table` | CSS table-display layout for labeled form fields |
|
|
138
|
-
| `.form-table-header` | Section heading inside `.form-table > th` |
|
|
139
|
-
| `.table` | Standard bordered table |
|
|
140
|
-
| `.table-inset` | Table variant without outer border |
|
|
141
|
-
| `.table-inline` | Table variant with `width: auto` |
|
|
142
|
-
| `.table-bd-v` | Vertical borders only |
|
|
143
|
-
| `.table-bd-h` | Horizontal borders only |
|
|
144
|
-
|
|
145
|
-
### Misc Utilities
|
|
146
|
-
|
|
147
|
-
| Class | Description |
|
|
148
|
-
|-------|-------------|
|
|
149
|
-
| `.fill` | `width: 100%; height: 100%; overflow: auto` |
|
|
150
|
-
| `.help` | Dotted underline + `cursor: help` |
|
|
151
|
-
| `.control-header` | Small gray label above a control |
|
|
152
|
-
| `.page-header` | Small gray section heading with bottom margin |
|
|
153
|
-
| `.sticky-top` | `position: sticky; top: 0; z-index: 1` |
|
|
154
|
-
| `.overflow-auto` | `overflow: auto` |
|
|
155
|
-
| `.position-relative` | `position: relative` |
|
|
156
|
-
| `.nowrap` | `white-space: nowrap` |
|
|
157
|
-
|
|
158
|
-
## CSS Custom Properties
|
|
159
|
-
|
|
160
|
-
### Color Palette
|
|
161
|
-
|
|
162
|
-
`--color-{name}` — Named colors from the palette: `red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`, `slate`, `gray`, `zinc`, `neutral`, `stone`.
|
|
163
|
-
|
|
164
|
-
### Theme Colors
|
|
165
|
-
|
|
166
|
-
`--theme-{group}-{shade}` — Groups: `gray`, `blue-gray`, `primary`, `secondary`, `info`, `success`, `warning`, `danger`. Shades: `lightest`, `lighter`, `light`, `default`, `dark`, `darker`, `darkest`.
|
|
167
|
-
|
|
168
|
-
### Transparency
|
|
169
|
-
|
|
170
|
-
| Property | Light Mode | Dark Mode |
|
|
171
|
-
|----------|-----------|-----------|
|
|
172
|
-
| `--trans-darkest` | `rgba(0,0,0,0.5)` | `rgba(255,255,255,0.5)` |
|
|
173
|
-
| `--trans-darker` | `rgba(0,0,0,0.4)` | `rgba(255,255,255,0.4)` |
|
|
174
|
-
| `--trans-dark` | `rgba(0,0,0,0.3)` | `rgba(255,255,255,0.3)` |
|
|
175
|
-
| `--trans-default` | `rgba(0,0,0,0.2)` | `rgba(255,255,255,0.2)` |
|
|
176
|
-
| `--trans-light` | `rgba(0,0,0,0.1)` | `rgba(255,255,255,0.1)` |
|
|
177
|
-
| `--trans-lighter` | `rgba(0,0,0,0.05)` | `rgba(255,255,255,0.03)` |
|
|
178
|
-
| `--trans-lightest` | `rgba(0,0,0,0.03)` | `rgba(255,255,255,0.05)` |
|
|
179
|
-
| `--trans-rev-default` | `rgba(255,255,255,0.1)` | `rgba(0,0,0,0.1)` |
|
|
180
|
-
| `--trans-rev-light` | `rgba(255,255,255,0.2)` | `rgba(0,0,0,0.2)` |
|
|
181
|
-
| `--trans-rev-lighter` | `rgba(255,255,255,0.3)` | `rgba(0,0,0,0.3)` |
|
|
182
|
-
| `--trans-rev-lightest` | `rgba(255,255,255,0.4)` | `rgba(0,0,0,0.4)` |
|
|
183
|
-
|
|
184
|
-
### Text Transparency
|
|
185
|
-
|
|
186
|
-
| Property | Light Mode | Dark Mode |
|
|
187
|
-
|----------|-----------|-----------|
|
|
188
|
-
| `--text-trans-dark` | `black` | `white` |
|
|
189
|
-
| `--text-trans-default` | `rgba(0,0,0,0.87)` | `rgba(255,255,255,0.87)` |
|
|
190
|
-
| `--text-trans-light` | `rgba(0,0,0,0.6)` | `rgba(255,255,255,0.6)` |
|
|
191
|
-
| `--text-trans-lighter` | `rgba(0,0,0,0.38)` | `rgba(255,255,255,0.38)` |
|
|
192
|
-
| `--text-trans-lightest` | `rgba(0,0,0,0.2)` | `rgba(255,255,255,0.2)` |
|
|
193
|
-
| `--text-trans-rev-default` | `white` | `black` |
|
|
194
|
-
| `--text-trans-rev-dark` | `rgba(255,255,255,0.7)` | `rgba(0,0,0,0.7)` |
|
|
195
|
-
| `--text-trans-rev-darker` | `rgba(255,255,255,0.5)` | `rgba(0,0,0,0.5)` |
|
|
196
|
-
|
|
197
|
-
### Font Sizes
|
|
198
|
-
|
|
199
|
-
| Property | Value |
|
|
200
|
-
|----------|-------|
|
|
201
|
-
| `--font-size-lg` | `1.1667rem` |
|
|
202
|
-
| `--font-size-default` | `1rem` |
|
|
203
|
-
| `--font-size-sm` | `0.9167rem` |
|
|
204
|
-
| `--font-size-h1` | `2rem` |
|
|
205
|
-
| `--font-size-h2` | `1.5rem` |
|
|
206
|
-
| `--font-size-h3` | `1.3333rem` |
|
|
207
|
-
| `--font-size-h4` | `1.1667rem` |
|
|
208
|
-
| `--font-size-h5` | `1rem` |
|
|
209
|
-
| `--font-size-h6` | `0.9167rem` |
|
|
210
|
-
|
|
211
|
-
### Gaps (Spacing Scale)
|
|
212
|
-
|
|
213
|
-
| Property | Value |
|
|
214
|
-
|----------|-------|
|
|
215
|
-
| `--gap-xxs` | `0.0833rem` |
|
|
216
|
-
| `--gap-xs` | `0.1667rem` |
|
|
217
|
-
| `--gap-sm` | `0.3333rem` |
|
|
218
|
-
| `--gap-default` | `0.5rem` |
|
|
219
|
-
| `--gap-lg` | `0.6667rem` |
|
|
220
|
-
| `--gap-xl` | `1rem` |
|
|
221
|
-
| `--gap-xxl` | `1.5rem` |
|
|
222
|
-
|
|
223
|
-
### Border Colors
|
|
224
|
-
|
|
225
|
-
| Property | Value |
|
|
226
|
-
|----------|-------|
|
|
227
|
-
| `--border-color-lighter` | `var(--theme-gray-lightest)` |
|
|
228
|
-
| `--border-color-light` | `var(--theme-gray-lighter)` |
|
|
229
|
-
| `--border-color-default` | `var(--theme-gray-light)` |
|
|
230
|
-
| `--border-color-dark` | `var(--theme-gray-default)` |
|
|
231
|
-
| `--border-color-darker` | `var(--theme-gray-dark)` |
|
|
232
|
-
|
|
233
|
-
### Border Radii
|
|
234
|
-
|
|
235
|
-
| Property | Value |
|
|
236
|
-
|----------|-------|
|
|
237
|
-
| `--border-radius-xs` | `0.0833rem` |
|
|
238
|
-
| `--border-radius-sm` | `0.1667rem` |
|
|
239
|
-
| `--border-radius-default` | `0.3333rem` |
|
|
240
|
-
| `--border-radius-lg` | `0.5rem` |
|
|
241
|
-
| `--border-radius-xl` | `0.6667rem` |
|
|
242
|
-
| `--border-radius-xxl` | `1rem` |
|
|
243
|
-
|
|
244
|
-
### Z-Index
|
|
245
|
-
|
|
246
|
-
| Property | Value |
|
|
247
|
-
|----------|-------|
|
|
248
|
-
| `--z-index-toast` | `9999` |
|
|
249
|
-
| `--z-index-busy` | `9998` |
|
|
250
|
-
| `--z-index-dropdown` | `5000` |
|
|
251
|
-
| `--z-index-modal` | `4000` |
|
|
252
|
-
| `--z-index-sidebar` | `3000` |
|
|
253
|
-
|
|
254
|
-
### Miscellaneous
|
|
255
|
-
|
|
256
|
-
| Property | Light Mode | Dark Mode |
|
|
257
|
-
|----------|-----------|-----------|
|
|
258
|
-
| `--line-height` | `1.5em` | — |
|
|
259
|
-
| `--font-family` | `sans-serif` | — |
|
|
260
|
-
| `--font-family-monospace` | `monospace` | — |
|
|
261
|
-
| `--background-color` | `white` | `#000` |
|
|
262
|
-
| `--background-rev-color` | `black` | `#fff` |
|
|
263
|
-
| `--control-color` | `white` | `#000` |
|
|
264
|
-
| `--busy-overlay-bg` | `rgba(255,255,255,0.6)` | `rgba(0,0,0,0.6)` |
|
|
265
|
-
| `--animation-duration` | `0.2s` | — |
|
|
266
|
-
| `--elevation-size` | `0.0833rem` | — |
|
|
267
|
-
| `--sidebar-width` | `15em` | — |
|
|
268
|
-
| `--topbar-height` | `3em` | — |
|
|
269
|
-
| `--sheet-pv` | `var(--gap-xs)` | — |
|
|
270
|
-
| `--sheet-ph` | `var(--gap-sm)` | — |
|
|
271
|
-
| `--sheet-bg` | `var(--theme-gray-lightest)` | — |
|
|
272
|
-
|
|
273
|
-
## Themes
|
|
274
|
-
|
|
275
|
-
### `.sd-theme-dark`
|
|
276
|
-
|
|
277
|
-
Overrides CSS custom properties for dark mode. Inverts `--trans-*`, `--text-trans-*`, `--theme-*` color maps, and sets `--background-color: #000`, `--control-color: #000`.
|
|
278
|
-
|
|
279
|
-
Images are automatically inverted via `filter: invert(1) hue-rotate(180deg)`. Add `.no-invert` class to opt out.
|
|
280
|
-
|
|
281
|
-
## Mixins / Functions
|
|
282
|
-
|
|
283
|
-
### `writeVars($value, $prevKey)`
|
|
284
|
-
|
|
285
|
-
Recursively walks a nested SASS map and emits each leaf as a CSS custom property `--{key}: {value}`.
|
|
286
|
-
|
|
287
|
-
### `elevation($value)`
|
|
288
|
-
|
|
289
|
-
Generates a `box-shadow` declaration for material-style elevation. Negative values produce inset shadows.
|
|
290
|
-
|
|
291
|
-
### `form-control-base()`
|
|
292
|
-
|
|
293
|
-
Emits base styles for form input controls (padding, border, font).
|
|
294
|
-
|
|
295
|
-
### `help()`
|
|
296
|
-
|
|
297
|
-
Applies dotted underline and `cursor: help`.
|
|
298
|
-
|
|
299
|
-
### `flex-direction($direction, $defaultGap: null)`
|
|
300
|
-
|
|
301
|
-
Sets `flex-direction` and optional `gap`. Includes fallback for browsers without flex gap support (Chrome 61+).
|
|
302
|
-
|
|
303
|
-
### `color-map($base, $offset: 0%)`
|
|
304
|
-
|
|
305
|
-
Returns a 7-shade map (`lightest`–`darkest`) by scaling the lightness of a base color.
|
|
306
|
-
|
|
307
|
-
### `to-rgb($oklch-color)`
|
|
308
|
-
|
|
309
|
-
Converts an OKLCH color value to RGB color space.
|