@sdcorejs/angular 20.0.0 → 20.0.3
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/README.md +36 -19
- package/assets/scss/core/_inline-edit.scss +105 -0
- package/assets/scss/core/form.scss +15 -0
- package/components/autoid-inspector/index.d.ts +53 -4
- package/components/form-generic/index.d.ts +12 -13
- package/components/index.d.ts +1 -0
- package/components/modal-resizable/index.d.ts +32 -0
- package/components/table/index.d.ts +99 -10
- package/components/view/index.d.ts +33 -0
- package/fesm2022/sdcorejs-angular-components-anchor.mjs +9 -9
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +111 -24
- package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-avatar.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-badge.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-base.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-button.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-chart.mjs +12 -12
- package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs +6 -6
- package/fesm2022/sdcorejs-angular-components-editor.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs +288 -375
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-history.mjs +7 -7
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs +10 -10
- package/fesm2022/sdcorejs-angular-components-inform.mjs +6 -6
- package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +158 -0
- package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-modal.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-operator.mjs +6 -4
- package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-preview.mjs +8 -8
- package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs +60 -106
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-quick-action.mjs +3 -3
- package/fesm2022/sdcorejs-angular-components-section.mjs +6 -6
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-splitter.mjs +12 -12
- package/fesm2022/sdcorejs-angular-components-stepper.mjs +6 -6
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs +18 -18
- package/fesm2022/sdcorejs-angular-components-tab.mjs +6 -6
- package/fesm2022/sdcorejs-angular-components-table.mjs +335 -208
- package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs +16 -16
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-view.mjs +45 -13
- package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components.mjs +1 -0
- package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-directives.mjs +21 -21
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +28 -8
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +11 -6
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +15 -10
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip.mjs +15 -10
- package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs +21 -12
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date.mjs +29 -17
- package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs +34 -22
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-directives.mjs +12 -12
- package/fesm2022/sdcorejs-angular-forms-inline-text.mjs +167 -0
- package/fesm2022/sdcorejs-angular-forms-inline-text.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs +7 -5
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs +37 -10
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input.mjs +38 -12
- package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-label.mjs +3 -3
- package/fesm2022/sdcorejs-angular-forms-models.mjs +32 -2
- package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-radio.mjs +11 -6
- package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-select.mjs +36 -12
- package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-switch.mjs +11 -6
- package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs +17 -7
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms.mjs +4 -4
- package/fesm2022/sdcorejs-angular-handlers.mjs +3 -3
- package/fesm2022/sdcorejs-angular-i18n.mjs +26 -6
- package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-interceptors.mjs +6 -6
- package/fesm2022/sdcorejs-angular-modules-auth.mjs +9 -9
- package/fesm2022/sdcorejs-angular-modules-authom.mjs +7 -7
- package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +7 -7
- package/fesm2022/sdcorejs-angular-modules-layout.mjs +73 -73
- package/fesm2022/sdcorejs-angular-modules-permission.mjs +9 -9
- package/fesm2022/sdcorejs-angular-pipes.mjs +14 -14
- package/fesm2022/sdcorejs-angular-services-api.mjs +10 -10
- package/fesm2022/sdcorejs-angular-services-cache.mjs +3 -3
- package/fesm2022/sdcorejs-angular-services-confirm.mjs +6 -6
- package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-docx.mjs +3 -3
- package/fesm2022/sdcorejs-angular-services-excel.mjs +3 -3
- package/fesm2022/sdcorejs-angular-services-license.mjs +3 -3
- package/fesm2022/sdcorejs-angular-services-loading.mjs +3 -3
- package/fesm2022/sdcorejs-angular-services-notify.mjs +23 -10
- package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-storage.mjs +3 -3
- package/forms/autocomplete/index.d.ts +16 -3
- package/forms/checkbox/index.d.ts +5 -1
- package/forms/chip/index.d.ts +5 -2
- package/forms/chip-calendar/index.d.ts +5 -2
- package/forms/date/index.d.ts +14 -5
- package/forms/date-range/index.d.ts +12 -5
- package/forms/datetime/index.d.ts +14 -5
- package/forms/inline-text/index.d.ts +80 -0
- package/forms/input/index.d.ts +14 -2
- package/forms/input-color/index.d.ts +3 -1
- package/forms/input-number/index.d.ts +14 -2
- package/forms/models/index.d.ts +40 -2
- package/forms/radio/index.d.ts +5 -2
- package/forms/select/index.d.ts +23 -5
- package/forms/switch/index.d.ts +5 -2
- package/forms/textarea/index.d.ts +9 -2
- package/i18n/index.d.ts +4 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# @sdcorejs/angular
|
|
2
2
|
|
|
3
|
-
>
|
|
4
|
-
> **EN** — Internal UI component library built on Angular Material, supporting Angular 19+
|
|
3
|
+
> Angular UI library built on Angular Material - supports Angular 19 / 20 / 21.
|
|
5
4
|
|
|
6
|
-
[](./package.json)
|
|
7
5
|
[](https://angular.dev)
|
|
8
6
|
[](https://material.angular.io)
|
|
9
7
|
|
|
8
|
+
**🚀 [Showcase](https://sdcorejs.github.io/sdcorejs-angular)** · **📖 [Storybook — code samples, props & API](https://sdcorejs.github.io/portal-template)**
|
|
9
|
+
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## Table of Contents / Mục lục
|
|
@@ -380,6 +380,25 @@ option: SdTableOption<Product> = {
|
|
|
380
380
|
<sd-table #sdTable [option]="option" />
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
+
**Tree rows / Dòng cây:**
|
|
384
|
+
|
|
385
|
+
`tree` là discriminated union theo `loadType`. Icon expand (`chevron_right` / `expand_more`) nằm ở **cột đầu** — cột STT khi bật `index`, ngược lại cột data đầu tiên — thụt lề theo cấp.
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// loadType: 'static' — children embedded sẵn trong mỗi row
|
|
389
|
+
tree: { loadType: 'static', childrenKey: 'children', defaultExpanded: 1 }
|
|
390
|
+
|
|
391
|
+
// loadType: 'lazy' — nạp con khi bung (Promise); hasChildren gate icon expand
|
|
392
|
+
tree: {
|
|
393
|
+
loadType: 'lazy',
|
|
394
|
+
hasChildren: (row) => row.type === 'Folder', // chỉ Folder mới có icon expand
|
|
395
|
+
onExpandChildren: (row) => api.getChildren(row.id), // () => Promise<T[]>
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
- **Child-level search** (`type: 'local'` + `loadType: 'static'`): lọc inline tìm cả **cấp con** — giữ nhánh cha của node khớp, ẩn sibling không khớp, tự bung tới node khớp. Clear filter khôi phục cây.
|
|
400
|
+
- **Lazy loading**: spinner hiện trong ô chevron khi `onExpandChildren` đang chạy; `hasChildren` quyết định dòng nào hiện icon (không truyền = mọi node đều hiện).
|
|
401
|
+
|
|
383
402
|
---
|
|
384
403
|
|
|
385
404
|
### SdAvatar
|
|
@@ -423,19 +442,18 @@ import {
|
|
|
423
442
|
SdSelect, // Dropdown
|
|
424
443
|
SdAutocomplete, // Autocomplete
|
|
425
444
|
SdDate, // Date picker
|
|
426
|
-
SdSearch, // Search với debounce
|
|
427
445
|
} from '@sdcorejs/angular/forms';
|
|
428
446
|
```
|
|
429
447
|
|
|
430
448
|
```html
|
|
431
|
-
<sd-input [(
|
|
449
|
+
<sd-input [(model)]="form.name" label="Họ tên" [required]="true" />
|
|
432
450
|
|
|
433
|
-
<sd-input-number [(
|
|
451
|
+
<sd-input-number [(model)]="form.price" label="Đơn giá" [min]="0" suffix="VNĐ" />
|
|
434
452
|
|
|
435
|
-
<sd-select [(
|
|
453
|
+
<sd-select [(model)]="form.status" label="Trạng thái"
|
|
436
454
|
[items]="statusList" valueField="value" displayField="label" />
|
|
437
455
|
|
|
438
|
-
<sd-date [(
|
|
456
|
+
<sd-date [(model)]="form.birthday" label="Ngày sinh" />
|
|
439
457
|
```
|
|
440
458
|
|
|
441
459
|
---
|
|
@@ -560,17 +578,17 @@ export class ProductListComponent implements OnInit {
|
|
|
560
578
|
<sd-section title="Thông tin sản phẩm" icon="inventory">
|
|
561
579
|
<div class="row">
|
|
562
580
|
<div class="col-6">
|
|
563
|
-
<sd-input [(
|
|
581
|
+
<sd-input [(model)]="formData.code" label="Mã" [required]="true" />
|
|
564
582
|
</div>
|
|
565
583
|
<div class="col-6">
|
|
566
|
-
<sd-select [(
|
|
584
|
+
<sd-select [(model)]="formData.status" label="Trạng thái"
|
|
567
585
|
[items]="STATUS_LIST" valueField="value" displayField="label" />
|
|
568
586
|
</div>
|
|
569
587
|
<div class="col-12">
|
|
570
|
-
<sd-input [(
|
|
588
|
+
<sd-input [(model)]="formData.name" label="Tên sản phẩm" [required]="true" />
|
|
571
589
|
</div>
|
|
572
590
|
<div class="col-6">
|
|
573
|
-
<sd-input-number [(
|
|
591
|
+
<sd-input-number [(model)]="formData.price" label="Đơn giá" suffix="VNĐ" />
|
|
574
592
|
</div>
|
|
575
593
|
</div>
|
|
576
594
|
</sd-section>
|
|
@@ -591,7 +609,7 @@ export class ProductListComponent implements OnInit {
|
|
|
591
609
|
### Cấu trúc thư viện / Project structure
|
|
592
610
|
|
|
593
611
|
```
|
|
594
|
-
|
|
612
|
+
sdcorejs-angular/
|
|
595
613
|
├── src/
|
|
596
614
|
│ └── public-api.ts # Entry point chính
|
|
597
615
|
├── assets/
|
|
@@ -704,20 +722,19 @@ ng-packagr -p ng-package.json --watch
|
|
|
704
722
|
|
|
705
723
|
### Versioning
|
|
706
724
|
|
|
707
|
-
|
|
725
|
+
Scheme: `<angular-major>.0.<release>`. Major digit **khoá theo Angular line** (19.x = Angular 19, 20.x = Angular 20, 21.x = Angular 21) — **KHÔNG** dùng để báo breaking. Mỗi release publish đồng thời 3 major cùng nội dung feature, chỉ khác Angular shim.
|
|
708
726
|
|
|
709
|
-
-
|
|
710
|
-
-
|
|
711
|
-
- `PATCH` — Bug fixes
|
|
727
|
+
- Luôn pin theo Angular line của bạn: `npm i @sdcorejs/angular@^19` (hoặc `@^20` / `@^21`).
|
|
728
|
+
- Breaking change được ghi rõ ở `CHANGELOG.md`, mục **Changed (BREAKING for consumers)**, kèm migration.
|
|
712
729
|
|
|
713
730
|
---
|
|
714
731
|
|
|
715
732
|
## QA / E2E
|
|
716
733
|
|
|
717
|
-
Core UI components expose runtime state via lowercase `data-*` attributes
|
|
734
|
+
Core UI components expose runtime state via lowercase `data-*` attributes for e2e selectors. The full catalog, component matrix, selector cookbook, and YAML schema for AI agents live in `docs/E2E-ATTRIBUTES.md` in the source repository.
|
|
718
735
|
|
|
719
736
|
---
|
|
720
737
|
|
|
721
738
|
## License
|
|
722
739
|
|
|
723
|
-
|
|
740
|
+
MIT - see the LICENSE file.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Shared `viewed='inline'` styles for sd-form-controls.
|
|
2
|
+
// why: 1 nguồn cho text-face + editor ẩn (panel control) và input borderless, tránh lặp ~40 dòng/control.
|
|
3
|
+
// Bare-flatten (mat-* internals) KHÔNG nằm ở đây — khác nhau theo control, giữ trong scss riêng.
|
|
4
|
+
|
|
5
|
+
// Clear-× — hover-gated, đặt cuối "mặt". Include BÊN TRONG rule của phần tử hover (face/input).
|
|
6
|
+
@mixin _inline-clear {
|
|
7
|
+
.sd-inline-clear {
|
|
8
|
+
display: none;
|
|
9
|
+
align-items: center;
|
|
10
|
+
margin-left: 4px;
|
|
11
|
+
padding: 0;
|
|
12
|
+
border: 0;
|
|
13
|
+
background: transparent;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
line-height: 0;
|
|
16
|
+
color: var(--sd-text-secondary, #6b7280);
|
|
17
|
+
transition: color 0.15s ease;
|
|
18
|
+
|
|
19
|
+
mat-icon {
|
|
20
|
+
font-size: 16px;
|
|
21
|
+
width: 16px;
|
|
22
|
+
height: 16px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&:hover {
|
|
26
|
+
color: var(--sd-error, #b32626);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&:hover .sd-inline-clear {
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Panel-based controls (select / date / datetime / date-range / autocomplete):
|
|
36
|
+
// `<sd-view>` text là "mặt" + trigger; editor render ẩn (overlay) chỉ để neo + mở panel.
|
|
37
|
+
@mixin sd-inline-panel {
|
|
38
|
+
// Neo cho .sd-inline-editor (absolute). Bare flatten + display nằm ở :host(.sd-bare) riêng của control.
|
|
39
|
+
:host(.sd-bare) {
|
|
40
|
+
position: relative;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.sd-inline-view {
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
width: 100%;
|
|
48
|
+
// why: nền nhẹ + đậm hơn khi hover → tín hiệu "viewed có thể bấm để sửa".
|
|
49
|
+
padding: 1px 6px;
|
|
50
|
+
border-radius: 4px;
|
|
51
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
52
|
+
transition: background-color 0.15s ease;
|
|
53
|
+
|
|
54
|
+
&:hover {
|
|
55
|
+
background-color: rgba(0, 0, 0, 0.08);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@include _inline-clear;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// why: editor vô hình phủ lên face. Tắt pointer-events CẢ cây con (mat-* tự bật lại ở trigger)
|
|
62
|
+
// để hover/click rơi xuống .sd-inline-view ở mọi chỗ. Panel mở qua enterInlineEdit() → open().
|
|
63
|
+
.sd-inline-editor {
|
|
64
|
+
position: absolute;
|
|
65
|
+
inset: 0;
|
|
66
|
+
opacity: 0;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
|
|
69
|
+
::ng-deep * {
|
|
70
|
+
pointer-events: none !important;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// NOTE: the former `sd-inline-input` mixin (mat-form-field flatten for the input/input-number
|
|
76
|
+
// inline variant) was removed when those controls moved to the <sd-inline-text> primitive
|
|
77
|
+
// (forms/inline-text), which owns its own borderless styling. The panel mixin above stays.
|
|
78
|
+
|
|
79
|
+
// Multiline input (textarea): no panel, no single-line `<sd-inline-text>` — flatten the
|
|
80
|
+
// mat-form-field so the `<textarea>` reads like text, transparent with a hover/focus affordance.
|
|
81
|
+
@mixin sd-inline-textarea {
|
|
82
|
+
.sd-inline-textarea {
|
|
83
|
+
cursor: text;
|
|
84
|
+
border-radius: 4px;
|
|
85
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
86
|
+
transition: background-color 0.15s ease;
|
|
87
|
+
|
|
88
|
+
&:hover {
|
|
89
|
+
background-color: rgba(0, 0, 0, 0.08);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&:focus-within {
|
|
93
|
+
background-color: rgba(0, 0, 0, 0.06);
|
|
94
|
+
box-shadow: inset 0 0 0 1px var(--sd-primary, #1f6feb);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
::ng-deep {
|
|
98
|
+
.mat-mdc-text-field-wrapper { padding: 0 6px; background: transparent; }
|
|
99
|
+
.mat-mdc-form-field-flex { padding: 0; }
|
|
100
|
+
.mdc-notched-outline { display: none; }
|
|
101
|
+
.mat-mdc-form-field-subscript-wrapper { display: none; }
|
|
102
|
+
.mat-mdc-form-field-infix { padding: 4px 0; min-height: 0; border: 0; }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -296,6 +296,21 @@ mat-checkbox {
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
+
// why: selector radio của <sd-table> (.c-selection, single mode) hiện một dấu chấm tối thừa
|
|
300
|
+
// nằm cạnh vòng radio. Nguồn gốc THẬT là state-layer padding của Material trên `.mdc-radio`
|
|
301
|
+
// (`padding: calc((var(--mdc-radio-state-layer-size) - 20px) / 2)`): trong cột selector, .c-selection
|
|
302
|
+
// bị scale(0.85) (xem table.component.scss) còn `.mdc-radio` có `will-change: transform` nên lên
|
|
303
|
+
// compositing layer riêng → phần `.mdc-radio__inner-circle` (transform: scale(0), border 10px màu
|
|
304
|
+
// tối) bị render rớt lại ~1px artifact trong dải padding đó, đọc thành "dấu chấm". Bỏ state-layer
|
|
305
|
+
// padding cho radio selector compact là khử sạch (vòng 20px + scale 0.85 vẫn căn giữa). Scope theo
|
|
306
|
+
// `.c-selection` nên KHÔNG ảnh hưởng radio ở nơi khác (giữ nguyên vùng hover/state-layer của chúng).
|
|
307
|
+
//
|
|
308
|
+
// LƯU Ý: cách trước (`label.mdc-label:empty { display:none }`) KHÔNG khử được dot — nó chỉ TÁCH dot
|
|
309
|
+
// thành 2 dấu chấm (label rỗng vốn đang phủ chồng lên artifact). Đã thay bằng fix dưới đây.
|
|
310
|
+
.c-selection.mat-mdc-radio-button .mdc-radio {
|
|
311
|
+
padding: 0;
|
|
312
|
+
}
|
|
313
|
+
|
|
299
314
|
// Placeholder mặc định 1rem (16px), mong muốn nên là 14px
|
|
300
315
|
.mat-mdc-floating-label {
|
|
301
316
|
font-size: 14px !important;
|
|
@@ -20,6 +20,9 @@ interface SdAutoidElementState {
|
|
|
20
20
|
minlength?: string;
|
|
21
21
|
pattern?: string;
|
|
22
22
|
errorMessage?: string;
|
|
23
|
+
type?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
message?: string;
|
|
23
26
|
}
|
|
24
27
|
interface SdAutoidElement {
|
|
25
28
|
stt: number;
|
|
@@ -42,6 +45,14 @@ interface SdAutoidElement {
|
|
|
42
45
|
* Used by the UI to group table-scoped elements into a separate section.
|
|
43
46
|
*/
|
|
44
47
|
tableScope?: string;
|
|
48
|
+
/**
|
|
49
|
+
* `true` when the element matched a required selector (sd-button, sd-input, …) but
|
|
50
|
+
* had NO `data-autoid` — the scanner still emits it with `autoid: ''` and a positional
|
|
51
|
+
* `xpath` fallback so the export stays usable. The dev should backfill an autoid.
|
|
52
|
+
*/
|
|
53
|
+
missingAutoid?: boolean;
|
|
54
|
+
/** Human-readable warning attached to a fallback element (only set when `missingAutoid`). */
|
|
55
|
+
warning?: string;
|
|
45
56
|
}
|
|
46
57
|
interface SdAutoidMissing {
|
|
47
58
|
tag: string;
|
|
@@ -119,14 +130,46 @@ declare class SdAutoidInspector implements OnDestroy {
|
|
|
119
130
|
|
|
120
131
|
type SdAutoidExportFormat = 'csv' | 'json' | 'md-pom' | 'md-table';
|
|
121
132
|
interface SdAutoidExportMeta {
|
|
133
|
+
/** `location.pathname + location.search` — kept for back-compat with MD exports. */
|
|
122
134
|
pageUrl: string;
|
|
123
135
|
pageTitle: string;
|
|
124
136
|
timestamp: string;
|
|
137
|
+
/** Full `location.href`. */
|
|
138
|
+
url: string;
|
|
139
|
+
/** `location.pathname` only. */
|
|
140
|
+
pathname: string;
|
|
141
|
+
/** Raw `location.search` (incl. leading `?`), or `''`. */
|
|
142
|
+
search: string;
|
|
143
|
+
/** Parsed query string → key/value map (last value wins on repeats). */
|
|
144
|
+
queryParams: Record<string, string>;
|
|
145
|
+
/**
|
|
146
|
+
* Angular route path params (`:id`, …) merged across the activated-route tree.
|
|
147
|
+
* Only present when an Angular `Router` is available at scan time; omitted otherwise.
|
|
148
|
+
*/
|
|
149
|
+
params?: Record<string, string>;
|
|
150
|
+
}
|
|
151
|
+
/** JSON export envelope: page meta + the scanned elements. */
|
|
152
|
+
interface SdAutoidExportJson {
|
|
153
|
+
meta: SdAutoidExportMeta;
|
|
154
|
+
elements: SdAutoidElement[];
|
|
125
155
|
}
|
|
126
156
|
|
|
127
157
|
declare class SdAutoidScannerService {
|
|
128
|
-
/**
|
|
129
|
-
|
|
158
|
+
/**
|
|
159
|
+
* Quét element có [data-autoid] trong root, gắn name/tag/value/xpath.
|
|
160
|
+
* Khi truyền `requireSelectors` (vd các sd-* form/button), những node khớp selector
|
|
161
|
+
* mà KHÔNG có data-autoid (self lẫn con) sẽ được thêm vào dưới dạng phần tử fallback
|
|
162
|
+
* (`autoid: ''`, xpath theo vị trí thẻ + cờ `missingAutoid` + warning) — để JSON xuất ra
|
|
163
|
+
* vẫn dùng được và dev biết chỗ cần bổ sung autoid.
|
|
164
|
+
*/
|
|
165
|
+
scan(root?: HTMLElement, requireSelectors?: ReadonlyArray<string>): SdAutoidElement[];
|
|
166
|
+
/**
|
|
167
|
+
* Tìm các node khớp `requireSelectors` nhưng thiếu data-autoid (self + mọi descendant),
|
|
168
|
+
* thêm vào `result` dưới dạng phần tử fallback. Trả về `stt` kế tiếp.
|
|
169
|
+
*/
|
|
170
|
+
private appendMissing;
|
|
171
|
+
/** XPath theo vị trí thẻ trong document, vd `(//sd-button)[2]`, khi không có autoid. */
|
|
172
|
+
private fallbackXpath;
|
|
130
173
|
/** Group element theo autoid để consumer lấy duplicate map. */
|
|
131
174
|
groupByAutoid(elements: SdAutoidElement[]): Record<string, SdAutoidElement[]>;
|
|
132
175
|
/**
|
|
@@ -177,7 +220,13 @@ declare class SdAutoidHighlightService {
|
|
|
177
220
|
}
|
|
178
221
|
|
|
179
222
|
declare class SdAutoidExportService {
|
|
180
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Có `meta` → bọc `{ meta, elements }` (kèm url/queryParams) để consumer biết trang/route.
|
|
225
|
+
* Không `meta` → giữ mảng thuần (back-compat cho caller cũ chỉ cần elements).
|
|
226
|
+
*/
|
|
227
|
+
toJson(elements: SdAutoidElement[], meta?: SdAutoidExportMeta): string;
|
|
228
|
+
/** Parse a `location.search` string into a flat key/value map (last value wins). */
|
|
229
|
+
parseQueryParams(search: string): Record<string, string>;
|
|
181
230
|
toCsv(elements: SdAutoidElement[]): string;
|
|
182
231
|
/** POM TypeScript skeleton — copy ngay vào file Playwright/Cypress. */
|
|
183
232
|
toMarkdownPom(elements: SdAutoidElement[], meta: SdAutoidExportMeta): string;
|
|
@@ -196,4 +245,4 @@ declare class SdAutoidExportService {
|
|
|
196
245
|
}
|
|
197
246
|
|
|
198
247
|
export { SD_AUTOID_DEFAULT_REQUIRE_SELECTORS, SdAutoidAuditService, SdAutoidExportService, SdAutoidHighlightService, SdAutoidInspector, SdAutoidScannerService };
|
|
199
|
-
export type { SdAutoidAuditResult, SdAutoidElement, SdAutoidElementState, SdAutoidExportFormat, SdAutoidExportMeta, SdAutoidInspectorConfig, SdAutoidMissing };
|
|
248
|
+
export type { SdAutoidAuditResult, SdAutoidElement, SdAutoidElementState, SdAutoidExportFormat, SdAutoidExportJson, SdAutoidExportMeta, SdAutoidInspectorConfig, SdAutoidMissing };
|
|
@@ -776,6 +776,9 @@ declare class SdFormBuilder extends SdBaseSecureComponent {
|
|
|
776
776
|
clonedVariables: SdFormGenericVariable[];
|
|
777
777
|
readonly selectedComponent: i0.WritableSignal<SdFormGenericComponent | SdFormGenericGroup | undefined>;
|
|
778
778
|
readonly isPreview: i0.WritableSignal<boolean>;
|
|
779
|
+
readonly editingGroupId: i0.WritableSignal<string | undefined>;
|
|
780
|
+
/** Group đang được Detail (tìm ở TOP-LEVEL theo id), undefined = đang ở canvas chính. */
|
|
781
|
+
readonly editingGroup: i0.Signal<SdFormGenericGroup | undefined>;
|
|
779
782
|
/** Signal toàn cục: TRUE khi BẤT KỲ cdkDrag nào đang active (palette, canvas, group, resize).
|
|
780
783
|
* Trigger class `.fb-shell--dragging` để ẩn hover/actions/resize toàn diện, không phụ thuộc :has(). */
|
|
781
784
|
readonly isAnyDragging: i0.WritableSignal<boolean>;
|
|
@@ -807,15 +810,17 @@ declare class SdFormBuilder extends SdBaseSecureComponent {
|
|
|
807
810
|
};
|
|
808
811
|
/** Segmented Design/Preview toggle (replaces play_circle/stop_circle). */
|
|
809
812
|
setMode: (preview: boolean) => void;
|
|
810
|
-
/**
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
|
|
814
|
-
|
|
813
|
+
/** Mở canvas thiết kế riêng cho 1 group (chỉ children của nó). Snapshot để Cancel revert. */
|
|
814
|
+
enterGroupEdit: (group: SdFormGenericGroup) => void;
|
|
815
|
+
/** OK: giữ thay đổi children, quay về canvas chính. */
|
|
816
|
+
confirmGroupEdit: () => void;
|
|
817
|
+
/** Cancel: revert children về snapshot lúc vào Detail, rồi quay về canvas chính. */
|
|
818
|
+
cancelGroupEdit: () => void;
|
|
819
|
+
/** Quick-add break sau row chỉ định (theo scope hiện tại — top-level hoặc group).
|
|
820
|
+
* Tính component index cuối cùng của row đó trong scope, splice break vào sau.
|
|
815
821
|
*/
|
|
816
822
|
insertBreakAfter: (row: DragDropRowItem) => void;
|
|
817
|
-
/**
|
|
818
|
-
removeFromGroup: (group: SdFormGenericGroup, id: string) => void;
|
|
823
|
+
/** Xoá component theo scope hiện tại (top-level hoặc children của group đang Detail). */
|
|
819
824
|
removeComponent: (id: string) => void;
|
|
820
825
|
selectComponent: (item?: SdFormGenericComponent | SdFormGenericGroup) => void;
|
|
821
826
|
onClickedOutside: (e: any) => void;
|
|
@@ -829,12 +834,6 @@ declare class SdFormBuilder extends SdBaseSecureComponent {
|
|
|
829
834
|
noReturnPredicate: () => boolean;
|
|
830
835
|
changeSizeControl: (event: CdkDragMove<SdFormGenericComponent | SdFormGenericGroup>, item: SdFormGenericComponent | SdFormGenericGroup, items: (SdFormGenericComponent | SdFormGenericGroup)[], currentIndex: number) => Promise<void>;
|
|
831
836
|
dragEndChangeSizeControl: (event: any) => void;
|
|
832
|
-
/** Resize a child item INSIDE a group.
|
|
833
|
-
* Math: lấy bounding của chính item, tính (mouse.x - item.left) / colWidth = newCols.
|
|
834
|
-
* Cách này đúng cho cả flex-wrap (item ở wrap row 2+) vì dùng item-relative,
|
|
835
|
-
* không phải sum-of-all-preceding-cols (sai khi item wrap xuống row mới).
|
|
836
|
-
*/
|
|
837
|
-
changeSizeChildInGroup: (event: CdkDragMove<SdFormGenericComponent>, child: SdFormGenericComponent, group: SdFormGenericGroup) => void;
|
|
838
837
|
onChangeViewed: (component: SdFormGenericComponent) => void;
|
|
839
838
|
onChangeHidden: (component: SdFormGenericComponent | SdFormGenericGroup) => void;
|
|
840
839
|
onDuplicate: (component: SdFormGenericComponent | SdFormGenericGroup) => void;
|
package/components/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from '@sdcorejs/angular/components/button';
|
|
|
3
3
|
export * from '@sdcorejs/angular/components/badge';
|
|
4
4
|
export * from '@sdcorejs/angular/components/tab-router';
|
|
5
5
|
export * from '@sdcorejs/angular/components/side-drawer';
|
|
6
|
+
export * from '@sdcorejs/angular/components/modal-resizable';
|
|
6
7
|
export * from '@sdcorejs/angular/components/modal';
|
|
7
8
|
export * from '@sdcorejs/angular/components/table';
|
|
8
9
|
export * from '@sdcorejs/angular/components/quick-action';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { CdkPortal } from '@angular/cdk/portal';
|
|
3
|
+
|
|
4
|
+
declare class SdModalResizable {
|
|
5
|
+
#private;
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly portal: _angular_core.Signal<CdkPortal>;
|
|
8
|
+
readonly editable: _angular_core.InputSignalWithTransform<boolean, boolean | "">;
|
|
9
|
+
readonly width: _angular_core.InputSignal<string>;
|
|
10
|
+
readonly editingChanged: _angular_core.OutputEmitterRef<boolean>;
|
|
11
|
+
readonly isEditing: _angular_core.WritableSignal<boolean>;
|
|
12
|
+
readonly isOpened: _angular_core.WritableSignal<boolean>;
|
|
13
|
+
readonly isHover: _angular_core.WritableSignal<boolean>;
|
|
14
|
+
readonly isLoading: _angular_core.WritableSignal<boolean>;
|
|
15
|
+
readonly isMinimum: _angular_core.WritableSignal<boolean>;
|
|
16
|
+
readonly isMaximum: _angular_core.WritableSignal<boolean>;
|
|
17
|
+
constructor();
|
|
18
|
+
open: () => void;
|
|
19
|
+
close: () => void;
|
|
20
|
+
minimize: () => void;
|
|
21
|
+
maximize: () => void;
|
|
22
|
+
toggleMaximum: () => void;
|
|
23
|
+
startLoading: () => void;
|
|
24
|
+
stopLoading: () => void;
|
|
25
|
+
toggleEditable(): void;
|
|
26
|
+
onFocus: () => void;
|
|
27
|
+
onBlur: () => void;
|
|
28
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdModalResizable, never>;
|
|
29
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdModalResizable, "sd-modal-resizable", never, { "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; }, { "editingChanged": "editingChanged"; }, never, ["[sdTitle]", "[sdBody]", "[sdFooter]"], true, never>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { SdModalResizable };
|
|
@@ -710,16 +710,103 @@ interface SdTableOptionStyle<T = any> {
|
|
|
710
710
|
rowCss?: (rowData: T, index?: number, ctx?: SdTableRowCssContext) => Record<string, string>;
|
|
711
711
|
}
|
|
712
712
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
713
|
+
/**
|
|
714
|
+
* Cấu hình tree-rows cho `<sd-table>` — render dòng con inline dưới dòng cha
|
|
715
|
+
* kèm expand/collapse.
|
|
716
|
+
*
|
|
717
|
+
* Đây là discriminated union theo `loadType`:
|
|
718
|
+
* - `'static'` ({@link TableOptionTreeStatic}) — children đã nằm sẵn trong data
|
|
719
|
+
* (embedded array tại `childrenKey`). Không gọi API khi bung.
|
|
720
|
+
* - `'lazy'` ({@link TableOptionTreeLazy}) — children nạp theo yêu cầu qua
|
|
721
|
+
* `onExpandChildren` khi người dùng bung dòng lần đầu.
|
|
722
|
+
*
|
|
723
|
+
* `loadType` là discriminant: TypeScript dựa vào nó để narrow union (vd chỉ
|
|
724
|
+
* `static` mới có `childrenKey`/`defaultExpanded`, chỉ `lazy` mới có
|
|
725
|
+
* `onExpandChildren`). Dùng type-guard `isLazyTree()` trong `tree.util.ts` để
|
|
726
|
+
* narrow an toàn thay vì truy cập field trực tiếp trên union.
|
|
727
|
+
*
|
|
728
|
+
* @example Static (children embedded)
|
|
729
|
+
* ```ts
|
|
730
|
+
* tree: { loadType: 'static', childrenKey: 'children', defaultExpanded: 1 }
|
|
731
|
+
* ```
|
|
732
|
+
* @example Lazy (nạp theo yêu cầu)
|
|
733
|
+
* ```ts
|
|
734
|
+
* tree: { loadType: 'lazy', onExpandChildren: row => api.getChildren(row.id) }
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
type SdTableOptionTree<T = any> = TableOptionTreeStatic<T> | TableOptionTreeLazy<T>;
|
|
738
|
+
/**
|
|
739
|
+
* Tree với dữ liệu children **embedded** sẵn trong mỗi row.
|
|
740
|
+
*
|
|
741
|
+
* Table đọc mảng con tại `childrenKey` ngay trên object data; không có lời gọi
|
|
742
|
+
* bất đồng bộ nào khi bung dòng. Đây cũng là chế độ hỗ trợ **search ở cấp con**
|
|
743
|
+
* cho table `type: 'local'` (xem `tree.util.ts#subtreeMatches` /
|
|
744
|
+
* `filterMatchingChildren`): khi lọc, một nhánh được giữ lại nếu chính nó hoặc
|
|
745
|
+
* bất kỳ hậu duệ nào khớp từ khoá, và nhánh khớp sẽ tự bung.
|
|
746
|
+
*/
|
|
747
|
+
interface TableOptionTreeStatic<T = any> {
|
|
748
|
+
/** Chế độ nạp children: dữ liệu đã embedded sẵn trong row. */
|
|
749
|
+
loadType: 'static';
|
|
750
|
+
/**
|
|
751
|
+
* Key trên object row chứa mảng children.
|
|
752
|
+
* Mặc định: `'children'`.
|
|
753
|
+
*/
|
|
754
|
+
childrenKey?: NestedKeyOf<T> | 'children';
|
|
755
|
+
/**
|
|
756
|
+
* Giới hạn độ sâu cây (level gốc = 0).
|
|
757
|
+
* `undefined` = không giới hạn.
|
|
758
|
+
*/
|
|
717
759
|
maxDepth?: number;
|
|
718
|
-
/**
|
|
760
|
+
/**
|
|
761
|
+
* Trạng thái bung mặc định khi load:
|
|
762
|
+
* - `false` — thu gọn hết (mặc định)
|
|
763
|
+
* - `true` — bung toàn bộ
|
|
764
|
+
* - `number N` — bung tới cấp `N` (row có `level < N` được bung)
|
|
765
|
+
*/
|
|
719
766
|
defaultExpanded?: boolean | number;
|
|
720
|
-
/**
|
|
721
|
-
|
|
722
|
-
|
|
767
|
+
/**
|
|
768
|
+
* Số pixel thụt lề (indent) cho mỗi cấp sâu.
|
|
769
|
+
* Mặc định: `20`.
|
|
770
|
+
*/
|
|
771
|
+
indentSize?: number;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Tree với children **nạp lười (lazy)** theo yêu cầu.
|
|
775
|
+
*
|
|
776
|
+
* Khi người dùng bung một dòng lần đầu mà dòng đó chưa có children embedded,
|
|
777
|
+
* table gọi `onExpandChildren(row)` để nạp; kết quả được cache lại trên row
|
|
778
|
+
* (ghi vào key `'children'`) nên các lần bung sau không gọi lại.
|
|
779
|
+
*
|
|
780
|
+
* Lazy tree **không hỗ trợ** `childrenKey` tuỳ biến (luôn dùng `'children'` làm
|
|
781
|
+
* nơi lưu kết quả) và **không hỗ trợ** `defaultExpanded` (không thể bung mặc
|
|
782
|
+
* định nhánh chưa nạp).
|
|
783
|
+
*/
|
|
784
|
+
interface TableOptionTreeLazy<T = any> {
|
|
785
|
+
/** Chế độ nạp children: nạp lười theo yêu cầu khi bung. */
|
|
786
|
+
loadType: 'lazy';
|
|
787
|
+
/**
|
|
788
|
+
* Giới hạn độ sâu cây (level gốc = 0).
|
|
789
|
+
* `undefined` = không giới hạn.
|
|
790
|
+
*/
|
|
791
|
+
maxDepth?: number;
|
|
792
|
+
/**
|
|
793
|
+
* Hàm nạp children khi bung dòng chưa có children embedded.
|
|
794
|
+
* Trả về `Promise<T[]>`; kết quả được ghi vào key `'children'` của row data
|
|
795
|
+
* và cache cho các lần bung sau.
|
|
796
|
+
*/
|
|
797
|
+
onExpandChildren: (rowData: T) => Promise<T[]>;
|
|
798
|
+
/**
|
|
799
|
+
* Xác định một row có con hay không — để quyết định có hiển thị icon expand.
|
|
800
|
+
* - Không truyền: MỌI lazy node đều hiện icon expand (không biết trước được).
|
|
801
|
+
* - Truyền: chỉ hiện icon khi trả `true`; trả `false` ⇒ row là lá (ẩn icon,
|
|
802
|
+
* không gọi `onExpandChildren`).
|
|
803
|
+
* Lưu ý: nếu row đã có children embedded sẵn thì luôn coi là có con (bỏ qua hàm này).
|
|
804
|
+
*/
|
|
805
|
+
hasChildren?: (rowData: T) => boolean;
|
|
806
|
+
/**
|
|
807
|
+
* Số pixel thụt lề (indent) cho mỗi cấp sâu.
|
|
808
|
+
* Mặc định: `20`.
|
|
809
|
+
*/
|
|
723
810
|
indentSize?: number;
|
|
724
811
|
}
|
|
725
812
|
|
|
@@ -954,8 +1041,10 @@ declare class MobileFilterComponent {
|
|
|
954
1041
|
|
|
955
1042
|
declare class ConfigComponent {
|
|
956
1043
|
#private;
|
|
1044
|
+
autoIdInput: _angular_core.InputSignal<string | null | undefined>;
|
|
957
1045
|
tableOption: _angular_core.InputSignal<SdTableOption | undefined>;
|
|
958
1046
|
changes: _angular_core.OutputEmitterRef<ConfiguredTableResult>;
|
|
1047
|
+
autoId: _angular_core.Signal<string>;
|
|
959
1048
|
modal: _angular_core.Signal<SdModal | undefined>;
|
|
960
1049
|
table: _angular_core.Signal<MatTable<SdTableColumn>>;
|
|
961
1050
|
configuration: _angular_core.WritableSignal<ConfiguredTable | undefined>;
|
|
@@ -969,7 +1058,7 @@ declare class ConfigComponent {
|
|
|
969
1058
|
handleMouseDown(): void;
|
|
970
1059
|
handleMouseUp(): void;
|
|
971
1060
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConfigComponent, never>;
|
|
972
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfigComponent, "config", never, { "tableOption": { "alias": "tableOption"; "required": false; "isSignal": true; }; }, { "changes": "changes"; }, never, never, true, never>;
|
|
1061
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfigComponent, "config", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "tableOption": { "alias": "tableOption"; "required": false; "isSignal": true; }; }, { "changes": "changes"; }, never, never, true, never>;
|
|
973
1062
|
}
|
|
974
1063
|
|
|
975
1064
|
declare class SdPopupExport {
|
|
@@ -1158,4 +1247,4 @@ declare class SdTable<T = unknown> extends SdBaseSecureComponent implements OnIn
|
|
|
1158
1247
|
}
|
|
1159
1248
|
|
|
1160
1249
|
export { MatPaginatorIntlCro, SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableGroupDefDirective, SdTableTitleDefDirective };
|
|
1161
|
-
export type { ISdTableConfiguration, SdTableColumn, SdTableColumnChildren, SdTableColumnLazyValues, SdTableColumnNormal, SdTableColumnTransformFunc, SdTableColumnValues, SdTableCommand, SdTableCommandChildren, SdTableCommandNormal, SdTableCommandOption, SdTableDisplay, SdTableExternalFilter, SdTableFilterRequest, SdTableGroupDefContext, SdTableItem, SdTableMeta, SdTableOption, SdTableOptionFilter, SdTableOptionTree, SdTableQuickFilter, TableFilterConfiguration, TableFilterRegister, TableFilterValue };
|
|
1250
|
+
export type { ISdTableConfiguration, SdTableColumn, SdTableColumnChildren, SdTableColumnLazyValues, SdTableColumnNormal, SdTableColumnTransformFunc, SdTableColumnValues, SdTableCommand, SdTableCommandChildren, SdTableCommandNormal, SdTableCommandOption, SdTableDisplay, SdTableExternalFilter, SdTableFilterRequest, SdTableGroupDefContext, SdTableItem, SdTableMeta, SdTableOption, SdTableOptionFilter, SdTableOptionTree, SdTableQuickFilter, TableFilterConfiguration, TableFilterRegister, TableFilterValue, TableOptionTreeLazy, TableOptionTreeStatic };
|
|
@@ -1,17 +1,50 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { TemplateRef } from '@angular/core';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* `<sd-view>` — pure read-only display of a value (text, hyperlink, or a custom template).
|
|
6
|
+
*
|
|
7
|
+
* Presentational proxy with no state of its own: the parent form control (`<sd-select>`,
|
|
8
|
+
* `<sd-input>`, …) computes the display string + resolved selection and passes them in;
|
|
9
|
+
* `<sd-view>` only decides WHICH template renders. It is the single rendering path for every
|
|
10
|
+
* "viewed" state across the form controls (DETAIL `viewed=true` and the `viewed='inline'`
|
|
11
|
+
* text face), so a custom `valueTemplate` (e.g. `sdViewDef` / `#sdValue`) looks identical in
|
|
12
|
+
* both. OnPush — re-renders only when an input signal changes.
|
|
13
|
+
*/
|
|
4
14
|
declare class SdView {
|
|
15
|
+
/** Optional label rendered above the value (omitted when a parent supplies its own label). */
|
|
5
16
|
label: _angular_core.InputSignal<string | null | undefined>;
|
|
17
|
+
/** Raw selected value — NOT rendered directly; only exposed in the `valueTemplate` context as `value`. */
|
|
6
18
|
value: _angular_core.InputSignal<any>;
|
|
19
|
+
/**
|
|
20
|
+
* Display string — what shows when no custom value template is bound.
|
|
21
|
+
* why: `input.required()` forces the parent to bind `[display]` (compile error otherwise),
|
|
22
|
+
* so the component never has to guess a fallback string from `value`.
|
|
23
|
+
*/
|
|
7
24
|
display: _angular_core.InputSignal<string | null | undefined>;
|
|
25
|
+
/** When set, the value renders as a link (`<a [sdHref]>`) instead of plain text. */
|
|
8
26
|
hyperlink: _angular_core.InputSignal<string | null | undefined>;
|
|
27
|
+
/** Label template handed down by a parent control (wins over `label` + `#sdLabel`). */
|
|
9
28
|
labelTemplate: _angular_core.InputSignal<TemplateRef<any> | undefined>;
|
|
29
|
+
/** Value template handed down by a parent control (wins over `display` + `#sdValue`). */
|
|
10
30
|
valueTemplate: _angular_core.InputSignal<TemplateRef<any> | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Resolved selected-item objects passed by the parent (e.g. `<sd-select>`).
|
|
33
|
+
* why: the parent owns option/lazy resolution — `<sd-view>` is a proxy and must NOT rebuild
|
|
34
|
+
* the list. Exposed in the value-template context so a "head +N" template can read `displayField`.
|
|
35
|
+
*/
|
|
11
36
|
selectedItems: _angular_core.InputSignal<any[] | undefined>;
|
|
37
|
+
/** `#sdLabel` template projected directly into `<sd-view>` (fallback when no `[labelTemplate]`). */
|
|
12
38
|
contentLabelTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
|
|
39
|
+
/** `#sdValue` template projected directly into `<sd-view>` (fallback when no `[valueTemplate]`). */
|
|
13
40
|
contentValueTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
|
|
41
|
+
/**
|
|
42
|
+
* Effective label template: input from parent wins, else the projected `#sdLabel`.
|
|
43
|
+
* why: `computed` caches the choice so the template's `@if (activeLabelTemplate())` doesn't
|
|
44
|
+
* re-evaluate two content-child reads on every change-detection pass.
|
|
45
|
+
*/
|
|
14
46
|
activeLabelTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
|
|
47
|
+
/** Effective value template: input from parent wins, else the projected `#sdValue`. Cached for the same reason. */
|
|
15
48
|
activeValueTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
|
|
16
49
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdView, never>;
|
|
17
50
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdView, "sd-view", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "display": { "alias": "display"; "required": true; "isSignal": true; }; "hyperlink": { "alias": "hyperlink"; "required": false; "isSignal": true; }; "labelTemplate": { "alias": "labelTemplate"; "required": false; "isSignal": true; }; "valueTemplate": { "alias": "valueTemplate"; "required": false; "isSignal": true; }; "selectedItems": { "alias": "selectedItems"; "required": false; "isSignal": true; }; }, {}, ["contentLabelTemplate", "contentValueTemplate"], never, true, never>;
|