@ni/ok-components 1.5.1 → 1.6.0

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.
Files changed (28) hide show
  1. package/dist/all-components-bundle.js +1224 -412
  2. package/dist/all-components-bundle.js.map +1 -1
  3. package/dist/all-components-bundle.min.js +5666 -5380
  4. package/dist/all-components-bundle.min.js.map +1 -1
  5. package/dist/custom-elements.json +538 -215
  6. package/dist/custom-elements.md +81 -19
  7. package/dist/esm/fv/all-fv.d.ts +2 -0
  8. package/dist/esm/fv/all-fv.js +2 -0
  9. package/dist/esm/fv/all-fv.js.map +1 -1
  10. package/dist/esm/fv/master-detail-list/index.d.ts +50 -0
  11. package/dist/esm/fv/master-detail-list/index.js +176 -0
  12. package/dist/esm/fv/master-detail-list/index.js.map +1 -0
  13. package/dist/esm/fv/master-detail-list/styles.d.ts +1 -0
  14. package/dist/esm/fv/master-detail-list/styles.js +68 -0
  15. package/dist/esm/fv/master-detail-list/styles.js.map +1 -0
  16. package/dist/esm/fv/master-detail-list/template.d.ts +2 -0
  17. package/dist/esm/fv/master-detail-list/template.js +36 -0
  18. package/dist/esm/fv/master-detail-list/template.js.map +1 -0
  19. package/dist/esm/fv/master-detail-list-item/index.d.ts +32 -0
  20. package/dist/esm/fv/master-detail-list-item/index.js +86 -0
  21. package/dist/esm/fv/master-detail-list-item/index.js.map +1 -0
  22. package/dist/esm/fv/master-detail-list-item/styles.d.ts +1 -0
  23. package/dist/esm/fv/master-detail-list-item/styles.js +100 -0
  24. package/dist/esm/fv/master-detail-list-item/styles.js.map +1 -0
  25. package/dist/esm/fv/master-detail-list-item/template.d.ts +2 -0
  26. package/dist/esm/fv/master-detail-list-item/template.js +28 -0
  27. package/dist/esm/fv/master-detail-list-item/template.js.map +1 -0
  28. package/package.json +2 -2
@@ -34,6 +34,46 @@
34
34
 
35
35
  <hr/>
36
36
 
37
+ ## class: `FvChipSelector`
38
+
39
+ ### Superclass
40
+
41
+ | Name | Module | Package |
42
+ | ------------------- | ------ | ------------------- |
43
+ | `FoundationElement` | | @ni/fast-foundation |
44
+
45
+ ### Fields
46
+
47
+ | Name | Privacy | Type | Default | Description | Inherited From |
48
+ | ------------------- | ------- | --------- | ----------------- | ----------- | -------------- |
49
+ | `disabled` | public | `boolean` | `false` | | |
50
+ | `open` | public | `boolean` | `false` | | |
51
+ | `label` | public | `string` | `''` | | |
52
+ | `selectedValues` | public | `string` | `''` | | |
53
+ | `options` | public | `string` | `''` | | |
54
+ | `placeholder` | public | `string` | `'Select values'` | | |
55
+ | `allowCustomValues` | public | `boolean` | `false` | | |
56
+
57
+ ### Events
58
+
59
+ | Name | Type | Description | Inherited From |
60
+ | -------- | ------------- | ----------- | -------------- |
61
+ | `change` | `CustomEvent` | | |
62
+
63
+ ### Attributes
64
+
65
+ | Name | Field | Inherited From |
66
+ | --------------------- | ----------------- | -------------- |
67
+ | `disabled` | disabled | |
68
+ | `open` | open | |
69
+ | `label` | label | |
70
+ | `selected-values` | selectedValues | |
71
+ | `options` | options | |
72
+ | `placeholder` | placeholder | |
73
+ | `allow-custom-values` | allowCustomValues | |
74
+
75
+ <hr/>
76
+
37
77
  ## class: `FvCard`
38
78
 
39
79
  ### Superclass
@@ -68,7 +108,7 @@
68
108
 
69
109
  <hr/>
70
110
 
71
- ## class: `FvChipSelector`
111
+ ## class: `FvMasterDetailList`
72
112
 
73
113
  ### Superclass
74
114
 
@@ -78,15 +118,9 @@
78
118
 
79
119
  ### Fields
80
120
 
81
- | Name | Privacy | Type | Default | Description | Inherited From |
82
- | ------------------- | ------- | --------- | ----------------- | ----------- | -------------- |
83
- | `disabled` | public | `boolean` | `false` | | |
84
- | `open` | public | `boolean` | `false` | | |
85
- | `label` | public | `string` | `''` | | |
86
- | `selectedValues` | public | `string` | `''` | | |
87
- | `options` | public | `string` | `''` | | |
88
- | `placeholder` | public | `string` | `'Select values'` | | |
89
- | `allowCustomValues` | public | `boolean` | `false` | | |
121
+ | Name | Privacy | Type | Default | Description | Inherited From |
122
+ | ------------- | ------- | -------- | ------------------- | ----------- | -------------- |
123
+ | `placeholder` | public | `string` | `'Filter items...'` | | |
90
124
 
91
125
  ### Events
92
126
 
@@ -96,15 +130,9 @@
96
130
 
97
131
  ### Attributes
98
132
 
99
- | Name | Field | Inherited From |
100
- | --------------------- | ----------------- | -------------- |
101
- | `disabled` | disabled | |
102
- | `open` | open | |
103
- | `label` | label | |
104
- | `selected-values` | selectedValues | |
105
- | `options` | options | |
106
- | `placeholder` | placeholder | |
107
- | `allow-custom-values` | allowCustomValues | |
133
+ | Name | Field | Inherited From |
134
+ | ------------- | ----------- | -------------- |
135
+ | `placeholder` | placeholder | |
108
136
 
109
137
  <hr/>
110
138
 
@@ -136,6 +164,40 @@
136
164
 
137
165
  <hr/>
138
166
 
167
+ ## class: `FvMasterDetailListItem`
168
+
169
+ ### Superclass
170
+
171
+ | Name | Module | Package |
172
+ | ------------------- | ------ | ------------------- |
173
+ | `FoundationElement` | | @ni/fast-foundation |
174
+
175
+ ### Fields
176
+
177
+ | Name | Privacy | Type | Default | Description | Inherited From |
178
+ | ------------- | ------- | --------- | ------- | ----------- | -------------- |
179
+ | `titleText` | public | `string` | `''` | | |
180
+ | `subtitle` | public | `string` | `''` | | |
181
+ | `value` | public | `string` | `''` | | |
182
+ | `compact` | public | `boolean` | `false` | | |
183
+ | `selected` | public | `boolean` | `false` | | |
184
+ | `statusColor` | public | `string` | `''` | | |
185
+ | `statusLabel` | public | `string` | `''` | | |
186
+
187
+ ### Attributes
188
+
189
+ | Name | Field | Inherited From |
190
+ | -------------- | ----------- | -------------- |
191
+ | `title-text` | titleText | |
192
+ | `subtitle` | subtitle | |
193
+ | `value` | value | |
194
+ | `compact` | compact | |
195
+ | `selected` | selected | |
196
+ | `status-color` | statusColor | |
197
+ | `status-label` | statusLabel | |
198
+
199
+ <hr/>
200
+
139
201
  ## class: `FvSearchInput`
140
202
 
141
203
  ### Superclass
@@ -2,6 +2,8 @@ import './accordion-item';
2
2
  import './card';
3
3
  import './chip-selector';
4
4
  import './context-help';
5
+ import './master-detail-list-item';
6
+ import './master-detail-list';
5
7
  import './split-button';
6
8
  import './split-button-anchor';
7
9
  import './summary-panel';
@@ -2,6 +2,8 @@ import './accordion-item';
2
2
  import './card';
3
3
  import './chip-selector';
4
4
  import './context-help';
5
+ import './master-detail-list-item';
6
+ import './master-detail-list';
5
7
  import './split-button';
6
8
  import './split-button-anchor';
7
9
  import './summary-panel';
@@ -1 +1 @@
1
- {"version":3,"file":"all-fv.js","sourceRoot":"","sources":["../../../src/fv/all-fv.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,QAAQ,CAAC;AAChB,OAAO,iBAAiB,CAAC;AACzB,OAAO,gBAAgB,CAAC;AACxB,OAAO,gBAAgB,CAAC;AACxB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,iBAAiB,CAAC;AACzB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,CAAC","sourcesContent":["import './accordion-item';\nimport './card';\nimport './chip-selector';\nimport './context-help';\nimport './split-button';\nimport './split-button-anchor';\nimport './summary-panel';\nimport './summary-panel-tile';\nimport './search-input';\n"]}
1
+ {"version":3,"file":"all-fv.js","sourceRoot":"","sources":["../../../src/fv/all-fv.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,QAAQ,CAAC;AAChB,OAAO,iBAAiB,CAAC;AACzB,OAAO,gBAAgB,CAAC;AACxB,OAAO,2BAA2B,CAAC;AACnC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,CAAC;AACxB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,iBAAiB,CAAC;AACzB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,CAAC","sourcesContent":["import './accordion-item';\nimport './card';\nimport './chip-selector';\nimport './context-help';\nimport './master-detail-list-item';\nimport './master-detail-list';\nimport './split-button';\nimport './split-button-anchor';\nimport './summary-panel';\nimport './summary-panel-tile';\nimport './search-input';\n"]}
@@ -0,0 +1,50 @@
1
+ import { FoundationElement } from '@ni/fast-foundation';
2
+ import { FvMasterDetailListItem } from '../master-detail-list-item';
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'ok-fv-master-detail-list': FvMasterDetailList;
6
+ }
7
+ }
8
+ export interface FvMasterDetailListChangeDetail {
9
+ item: FvMasterDetailListItem | null;
10
+ value: string | null;
11
+ }
12
+ /**
13
+ * A filterable master-detail list with keyboard selection.
14
+ */
15
+ export declare class FvMasterDetailList extends FoundationElement {
16
+ placeholder: string;
17
+ /** @internal */
18
+ filterText: string;
19
+ /** @internal */
20
+ activeItemId: string | null;
21
+ /** @internal */
22
+ items: FvMasterDetailListItem[];
23
+ /** @internal */
24
+ readonly inputId: string;
25
+ /** @internal */
26
+ readonly listboxId: string;
27
+ private filterInput;
28
+ private selectedItem;
29
+ /** @internal */
30
+ connectedCallback(): void;
31
+ /** @internal */
32
+ filterTextChanged(): void;
33
+ /** @internal */
34
+ captureFilterInput(input: HTMLInputElement | null): void;
35
+ /** @internal */
36
+ get hasVisibleItems(): boolean;
37
+ /** @internal */
38
+ handleFilterInput(event: Event): void;
39
+ /** @internal */
40
+ handleFilterKeydown(event: KeyboardEvent): boolean;
41
+ /** @internal */
42
+ handleItemsSlotChange(): void;
43
+ /** @internal */
44
+ handleItemsClick(event: Event): void;
45
+ private get visibleItems();
46
+ private refreshItems;
47
+ private applyFilter;
48
+ private setSelectedItem;
49
+ }
50
+ export declare const fvMasterDetailListTag = "ok-fv-master-detail-list";
@@ -0,0 +1,176 @@
1
+ import { __decorate } from "tslib";
2
+ import { attr, observable } from '@ni/fast-element';
3
+ import { DesignSystem, FoundationElement } from '@ni/fast-foundation';
4
+ import { uniqueId } from '@ni/fast-web-utilities';
5
+ import { diacriticInsensitiveStringNormalizer } from '@ni/nimble-components/dist/esm/utilities/models/string-normalizers';
6
+ import { FvMasterDetailListItem, fvMasterDetailListItemTag } from '../master-detail-list-item';
7
+ import { styles } from './styles';
8
+ import { template } from './template';
9
+ /**
10
+ * A filterable master-detail list with keyboard selection.
11
+ */
12
+ export class FvMasterDetailList extends FoundationElement {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.placeholder = 'Filter items...';
16
+ /** @internal */
17
+ this.filterText = '';
18
+ /** @internal */
19
+ this.activeItemId = null;
20
+ /** @internal */
21
+ this.items = [];
22
+ /** @internal */
23
+ this.inputId = uniqueId('ok-fv-master-detail-list-input');
24
+ /** @internal */
25
+ this.listboxId = uniqueId('ok-fv-master-detail-list-listbox');
26
+ this.filterInput = null;
27
+ this.selectedItem = null;
28
+ }
29
+ /** @internal */
30
+ connectedCallback() {
31
+ super.connectedCallback();
32
+ queueMicrotask(() => {
33
+ this.refreshItems();
34
+ });
35
+ }
36
+ /** @internal */
37
+ filterTextChanged() {
38
+ if (this.$fastController.isConnected) {
39
+ this.applyFilter(true);
40
+ }
41
+ }
42
+ /** @internal */
43
+ captureFilterInput(input) {
44
+ this.filterInput = input;
45
+ }
46
+ /** @internal */
47
+ get hasVisibleItems() {
48
+ return this.visibleItems.length > 0;
49
+ }
50
+ /** @internal */
51
+ handleFilterInput(event) {
52
+ const input = event.target;
53
+ this.filterText = input.value;
54
+ }
55
+ /** @internal */
56
+ handleFilterKeydown(event) {
57
+ if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
58
+ return true;
59
+ }
60
+ const visibleItems = this.visibleItems;
61
+ if (visibleItems.length === 0) {
62
+ event.preventDefault();
63
+ return false;
64
+ }
65
+ const currentIndex = visibleItems.findIndex(item => item.selected);
66
+ let startingIndex = currentIndex;
67
+ if (startingIndex < 0) {
68
+ startingIndex = event.key === 'ArrowDown' ? -1 : visibleItems.length;
69
+ }
70
+ const nextIndex = event.key === 'ArrowDown'
71
+ ? Math.min(startingIndex + 1, visibleItems.length - 1)
72
+ : Math.max(startingIndex - 1, 0);
73
+ this.setSelectedItem(visibleItems[nextIndex] ?? null, true);
74
+ visibleItems[nextIndex]?.scrollIntoView({ block: 'nearest' });
75
+ event.preventDefault();
76
+ return false;
77
+ }
78
+ /** @internal */
79
+ handleItemsSlotChange() {
80
+ this.refreshItems();
81
+ }
82
+ /** @internal */
83
+ handleItemsClick(event) {
84
+ const item = event.composedPath().find(pathItem => pathItem instanceof HTMLElement && pathItem.localName === fvMasterDetailListItemTag);
85
+ if (!item || item.hidden) {
86
+ return;
87
+ }
88
+ this.setSelectedItem(item, true);
89
+ this.filterInput?.focus();
90
+ }
91
+ get visibleItems() {
92
+ return this.items.filter(item => !item.hidden);
93
+ }
94
+ refreshItems() {
95
+ const slot = this.shadowRoot?.querySelector('slot');
96
+ const assignedItems = slot?.assignedElements({ flatten: true }).filter(element => element instanceof HTMLElement && element.localName === fvMasterDetailListItemTag);
97
+ this.items = assignedItems ?? [];
98
+ for (const item of this.items) {
99
+ if (item.id.length === 0) {
100
+ item.id = uniqueId('ok-fv-master-detail-list-item');
101
+ }
102
+ }
103
+ this.applyFilter(false);
104
+ }
105
+ applyFilter(emitSelectionChange) {
106
+ const normalizedFilter = diacriticInsensitiveStringNormalizer(this.filterText.trim());
107
+ let firstVisibleItem = null;
108
+ for (const item of this.items) {
109
+ const searchableText = diacriticInsensitiveStringNormalizer(`${item.titleText} ${item.subtitle} ${item.value}`.trim());
110
+ const matches = normalizedFilter.length === 0 || searchableText.includes(normalizedFilter);
111
+ item.hidden = !matches;
112
+ if (matches && firstVisibleItem === null) {
113
+ firstVisibleItem = item;
114
+ }
115
+ }
116
+ const visibleSelectedItems = this.visibleItems.filter(item => item.selected);
117
+ const preferredSelectedItem = visibleSelectedItems[0] ?? null;
118
+ for (const extraSelectedItem of visibleSelectedItems.slice(1)) {
119
+ extraSelectedItem.selected = false;
120
+ }
121
+ if (preferredSelectedItem) {
122
+ this.setSelectedItem(preferredSelectedItem, emitSelectionChange && preferredSelectedItem !== this.selectedItem);
123
+ return;
124
+ }
125
+ this.setSelectedItem(firstVisibleItem, emitSelectionChange && firstVisibleItem !== this.selectedItem);
126
+ }
127
+ setSelectedItem(nextItem, emitChange) {
128
+ if (this.selectedItem === nextItem) {
129
+ return;
130
+ }
131
+ if (this.selectedItem) {
132
+ this.selectedItem.selected = false;
133
+ }
134
+ this.selectedItem = nextItem;
135
+ if (this.selectedItem) {
136
+ this.selectedItem.selected = true;
137
+ this.activeItemId = this.selectedItem.id;
138
+ }
139
+ else {
140
+ this.activeItemId = null;
141
+ }
142
+ if (emitChange) {
143
+ this.dispatchEvent(new CustomEvent('change', {
144
+ bubbles: true,
145
+ composed: true,
146
+ detail: {
147
+ item: this.selectedItem,
148
+ value: this.selectedItem?.value || this.selectedItem?.titleText || null
149
+ }
150
+ }));
151
+ }
152
+ }
153
+ }
154
+ __decorate([
155
+ attr
156
+ ], FvMasterDetailList.prototype, "placeholder", void 0);
157
+ __decorate([
158
+ observable
159
+ ], FvMasterDetailList.prototype, "filterText", void 0);
160
+ __decorate([
161
+ observable
162
+ ], FvMasterDetailList.prototype, "activeItemId", void 0);
163
+ __decorate([
164
+ observable
165
+ ], FvMasterDetailList.prototype, "items", void 0);
166
+ const okFvMasterDetailList = FvMasterDetailList.compose({
167
+ baseName: 'fv-master-detail-list',
168
+ template,
169
+ styles,
170
+ shadowOptions: {
171
+ delegatesFocus: true
172
+ }
173
+ });
174
+ DesignSystem.getOrCreate().withPrefix('ok').register(okFvMasterDetailList());
175
+ export const fvMasterDetailListTag = 'ok-fv-master-detail-list';
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fv/master-detail-list/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { attr, observable } from '@ni/fast-element';\nimport { DesignSystem, FoundationElement } from '@ni/fast-foundation';\nimport { uniqueId } from '@ni/fast-web-utilities';\nimport { diacriticInsensitiveStringNormalizer } from '@ni/nimble-components/dist/esm/utilities/models/string-normalizers';\nimport { FvMasterDetailListItem, fvMasterDetailListItemTag } from '../master-detail-list-item';\nimport { styles } from './styles';\nimport { template } from './template';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ok-fv-master-detail-list': FvMasterDetailList;\n }\n}\n\nexport interface FvMasterDetailListChangeDetail {\n item: FvMasterDetailListItem | null;\n value: string | null;\n}\n\n/**\n * A filterable master-detail list with keyboard selection.\n */\nexport class FvMasterDetailList extends FoundationElement {\n @attr\n public placeholder = 'Filter items...';\n\n /** @internal */\n @observable\n public filterText = '';\n\n /** @internal */\n @observable\n public activeItemId: string | null = null;\n\n /** @internal */\n @observable\n public items: FvMasterDetailListItem[] = [];\n\n /** @internal */\n public readonly inputId = uniqueId('ok-fv-master-detail-list-input');\n\n /** @internal */\n public readonly listboxId = uniqueId('ok-fv-master-detail-list-listbox');\n\n private filterInput: HTMLInputElement | null = null;\n\n private selectedItem: FvMasterDetailListItem | null = null;\n\n /** @internal */\n public override connectedCallback(): void {\n super.connectedCallback();\n queueMicrotask(() => {\n this.refreshItems();\n });\n }\n\n /** @internal */\n public filterTextChanged(): void {\n if (this.$fastController.isConnected) {\n this.applyFilter(true);\n }\n }\n\n /** @internal */\n public captureFilterInput(input: HTMLInputElement | null): void {\n this.filterInput = input;\n }\n\n /** @internal */\n public get hasVisibleItems(): boolean {\n return this.visibleItems.length > 0;\n }\n\n /** @internal */\n public handleFilterInput(event: Event): void {\n const input = event.target as HTMLInputElement;\n this.filterText = input.value;\n }\n\n /** @internal */\n public handleFilterKeydown(event: KeyboardEvent): boolean {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {\n return true;\n }\n\n const visibleItems = this.visibleItems;\n if (visibleItems.length === 0) {\n event.preventDefault();\n return false;\n }\n\n const currentIndex = visibleItems.findIndex(item => item.selected);\n let startingIndex = currentIndex;\n\n if (startingIndex < 0) {\n startingIndex = event.key === 'ArrowDown' ? -1 : visibleItems.length;\n }\n\n const nextIndex = event.key === 'ArrowDown'\n ? Math.min(startingIndex + 1, visibleItems.length - 1)\n : Math.max(startingIndex - 1, 0);\n\n this.setSelectedItem(visibleItems[nextIndex] ?? null, true);\n visibleItems[nextIndex]?.scrollIntoView({ block: 'nearest' });\n event.preventDefault();\n return false;\n }\n\n /** @internal */\n public handleItemsSlotChange(): void {\n this.refreshItems();\n }\n\n /** @internal */\n public handleItemsClick(event: Event): void {\n const item = event.composedPath().find(\n pathItem => pathItem instanceof HTMLElement && pathItem.localName === fvMasterDetailListItemTag\n ) as FvMasterDetailListItem | undefined;\n\n if (!item || item.hidden) {\n return;\n }\n\n this.setSelectedItem(item, true);\n this.filterInput?.focus();\n }\n\n private get visibleItems(): FvMasterDetailListItem[] {\n return this.items.filter(item => !item.hidden);\n }\n\n private refreshItems(): void {\n const slot = this.shadowRoot?.querySelector('slot');\n const assignedItems = slot?.assignedElements({ flatten: true }).filter(\n element => element instanceof HTMLElement && element.localName === fvMasterDetailListItemTag\n ) as FvMasterDetailListItem[] | undefined;\n\n this.items = assignedItems ?? [];\n for (const item of this.items) {\n if (item.id.length === 0) {\n item.id = uniqueId('ok-fv-master-detail-list-item');\n }\n }\n\n this.applyFilter(false);\n }\n\n private applyFilter(emitSelectionChange: boolean): void {\n const normalizedFilter = diacriticInsensitiveStringNormalizer(this.filterText.trim());\n let firstVisibleItem: FvMasterDetailListItem | null = null;\n\n for (const item of this.items) {\n const searchableText = diacriticInsensitiveStringNormalizer(\n `${item.titleText} ${item.subtitle} ${item.value}`.trim()\n );\n const matches = normalizedFilter.length === 0 || searchableText.includes(normalizedFilter);\n item.hidden = !matches;\n\n if (matches && firstVisibleItem === null) {\n firstVisibleItem = item;\n }\n }\n\n const visibleSelectedItems = this.visibleItems.filter(item => item.selected);\n const preferredSelectedItem = visibleSelectedItems[0] ?? null;\n\n for (const extraSelectedItem of visibleSelectedItems.slice(1)) {\n extraSelectedItem.selected = false;\n }\n\n if (preferredSelectedItem) {\n this.setSelectedItem(\n preferredSelectedItem,\n emitSelectionChange && preferredSelectedItem !== this.selectedItem\n );\n return;\n }\n\n this.setSelectedItem(\n firstVisibleItem,\n emitSelectionChange && firstVisibleItem !== this.selectedItem\n );\n }\n\n private setSelectedItem(nextItem: FvMasterDetailListItem | null, emitChange: boolean): void {\n if (this.selectedItem === nextItem) {\n return;\n }\n\n if (this.selectedItem) {\n this.selectedItem.selected = false;\n }\n\n this.selectedItem = nextItem;\n\n if (this.selectedItem) {\n this.selectedItem.selected = true;\n this.activeItemId = this.selectedItem.id;\n } else {\n this.activeItemId = null;\n }\n\n if (emitChange) {\n this.dispatchEvent(new CustomEvent<FvMasterDetailListChangeDetail>('change', {\n bubbles: true,\n composed: true,\n detail: {\n item: this.selectedItem,\n value: this.selectedItem?.value || this.selectedItem?.titleText || null\n }\n }));\n }\n }\n}\n\nconst okFvMasterDetailList = FvMasterDetailList.compose({\n baseName: 'fv-master-detail-list',\n template,\n styles,\n shadowOptions: {\n delegatesFocus: true\n }\n});\n\nDesignSystem.getOrCreate().withPrefix('ok').register(okFvMasterDetailList());\nexport const fvMasterDetailListTag = 'ok-fv-master-detail-list';"]}
@@ -0,0 +1 @@
1
+ export declare const styles: import("@ni/fast-element").ElementStyles;
@@ -0,0 +1,68 @@
1
+ import { css } from '@ni/fast-element';
2
+ import { bodyFont, bodyFontColor, borderHoverColor, borderRgbPartialColor, borderWidth, placeholderFontColor, smallDelay, standardPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens';
3
+ import { display } from '../../utilities/style/display';
4
+ export const styles = css `
5
+ @layer base, hover, focusVisible;
6
+
7
+ @layer base {
8
+ ${display('block')}
9
+
10
+ :host {
11
+ color: ${bodyFontColor};
12
+ font: ${bodyFont};
13
+ }
14
+
15
+ .master-detail-list {
16
+ display: flex;
17
+ flex-direction: column;
18
+ min-block-size: 0;
19
+ }
20
+
21
+ .filter-row {
22
+ padding: ${standardPadding};
23
+ padding-block-end: 10px;
24
+ }
25
+
26
+ .filter-input {
27
+ -webkit-appearance: none;
28
+ appearance: none;
29
+ inline-size: 100%;
30
+ padding: 10px 2px 12px;
31
+ font: inherit;
32
+ color: inherit;
33
+ border: none;
34
+ border-bottom: ${borderWidth} solid rgba(${borderRgbPartialColor}, 0.35);
35
+ background: transparent;
36
+ outline: none;
37
+ transition: border-color ${smallDelay} ease-in-out;
38
+ }
39
+
40
+ .filter-input::placeholder {
41
+ color: ${placeholderFontColor};
42
+ }
43
+
44
+ .items {
45
+ display: block;
46
+ min-block-size: 0;
47
+ overflow: auto;
48
+ }
49
+
50
+ .empty-state {
51
+ padding: 18px;
52
+ color: ${placeholderFontColor};
53
+ }
54
+ }
55
+
56
+ @layer hover {
57
+ .filter-input:hover {
58
+ border-bottom-color: ${borderHoverColor};
59
+ }
60
+ }
61
+
62
+ @layer focusVisible {
63
+ .filter-input:focus-visible {
64
+ border-bottom-color: ${borderHoverColor};
65
+ }
66
+ }
67
+ `;
68
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../src/fv/master-detail-list/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EACH,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,WAAW,EACX,oBAAoB,EACpB,UAAU,EACV,eAAe,EAClB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAExD,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;UAIf,OAAO,CAAC,OAAO,CAAC;;;qBAGL,aAAa;oBACd,QAAQ;;;;;;;;;;uBAUL,eAAe;;;;;;;;;;;;6BAYT,WAAW,eAAe,qBAAqB;;;uCAGrC,UAAU;;;;qBAI5B,oBAAoB;;;;;;;;;;;qBAWpB,oBAAoB;;;;;;mCAMN,gBAAgB;;;;;;mCAMhB,gBAAgB;;;CAGlD,CAAC","sourcesContent":["import { css } from '@ni/fast-element';\nimport {\n bodyFont,\n bodyFontColor,\n borderHoverColor,\n borderRgbPartialColor,\n borderWidth,\n placeholderFontColor,\n smallDelay,\n standardPadding\n} from '@ni/nimble-components/dist/esm/theme-provider/design-tokens';\nimport { display } from '../../utilities/style/display';\n\nexport const styles = css`\n @layer base, hover, focusVisible;\n\n @layer base {\n ${display('block')}\n\n :host {\n color: ${bodyFontColor};\n font: ${bodyFont};\n }\n\n .master-detail-list {\n display: flex;\n flex-direction: column;\n min-block-size: 0;\n }\n\n .filter-row {\n padding: ${standardPadding};\n padding-block-end: 10px;\n }\n\n .filter-input {\n -webkit-appearance: none;\n appearance: none;\n inline-size: 100%;\n padding: 10px 2px 12px;\n font: inherit;\n color: inherit;\n border: none;\n border-bottom: ${borderWidth} solid rgba(${borderRgbPartialColor}, 0.35);\n background: transparent;\n outline: none;\n transition: border-color ${smallDelay} ease-in-out;\n }\n\n .filter-input::placeholder {\n color: ${placeholderFontColor};\n }\n\n .items {\n display: block;\n min-block-size: 0;\n overflow: auto;\n }\n\n .empty-state {\n padding: 18px;\n color: ${placeholderFontColor};\n }\n }\n\n @layer hover {\n .filter-input:hover {\n border-bottom-color: ${borderHoverColor};\n }\n }\n\n @layer focusVisible {\n .filter-input:focus-visible {\n border-bottom-color: ${borderHoverColor};\n }\n }\n`;"]}
@@ -0,0 +1,2 @@
1
+ import type { FvMasterDetailList } from '.';
2
+ export declare const template: import("@ni/fast-element").ViewTemplate<FvMasterDetailList, any>;
@@ -0,0 +1,36 @@
1
+ import { html, ref, when } from '@ni/fast-element';
2
+ export const template = html `
3
+ <div class="master-detail-list">
4
+ <div class="filter-row">
5
+ <input
6
+ id="${x => x.inputId}"
7
+ class="filter-input"
8
+ type="text"
9
+ placeholder="${x => x.placeholder}"
10
+ :value="${x => x.filterText}"
11
+ aria-controls="${x => x.listboxId}"
12
+ aria-activedescendant="${x => x.activeItemId}"
13
+ aria-label="${x => x.placeholder}"
14
+ role="combobox"
15
+ aria-haspopup="listbox"
16
+ aria-autocomplete="list"
17
+ aria-expanded="true"
18
+ ${ref('captureFilterInput')}
19
+ @input="${(x, c) => x.handleFilterInput(c.event)}"
20
+ @keydown="${(x, c) => x.handleFilterKeydown(c.event)}"
21
+ />
22
+ </div>
23
+ <div
24
+ id="${x => x.listboxId}"
25
+ class="items"
26
+ role="listbox"
27
+ @click="${(x, c) => x.handleItemsClick(c.event)}"
28
+ >
29
+ <slot @slotchange="${x => x.handleItemsSlotChange()}"></slot>
30
+ ${when(x => !x.hasVisibleItems, html `
31
+ <div class="empty-state">No matches</div>
32
+ `)}
33
+ </div>
34
+ </div>
35
+ `;
36
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../../src/fv/master-detail-list/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAoB;;;;sBAI1B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;;;+BAGL,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;0BACvB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU;iCACV,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;yCACR,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY;8BAC9B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;;;;;kBAK9B,GAAG,CAAC,oBAAoB,CAAC;0BACjB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC;4BACpC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAsB,CAAC;;;;kBAInE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;;;sBAGZ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC;;iCAE1B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE;cACjD,IAAI,CACF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,EACvB,IAAI,CAAoB;;iBAEvB,CACJ;;;CAGZ,CAAC","sourcesContent":["import { html, ref, when } from '@ni/fast-element';\nimport type { FvMasterDetailList } from '.';\n\nexport const template = html<FvMasterDetailList>`\n <div class=\"master-detail-list\">\n <div class=\"filter-row\">\n <input\n id=\"${x => x.inputId}\"\n class=\"filter-input\"\n type=\"text\"\n placeholder=\"${x => x.placeholder}\"\n :value=\"${x => x.filterText}\"\n aria-controls=\"${x => x.listboxId}\"\n aria-activedescendant=\"${x => x.activeItemId}\"\n aria-label=\"${x => x.placeholder}\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-expanded=\"true\"\n ${ref('captureFilterInput')}\n @input=\"${(x, c) => x.handleFilterInput(c.event)}\"\n @keydown=\"${(x, c) => x.handleFilterKeydown(c.event as KeyboardEvent)}\"\n />\n </div>\n <div\n id=\"${x => x.listboxId}\"\n class=\"items\"\n role=\"listbox\"\n @click=\"${(x, c) => x.handleItemsClick(c.event)}\"\n >\n <slot @slotchange=\"${x => x.handleItemsSlotChange()}\"></slot>\n ${when(\n x => !x.hasVisibleItems,\n html<FvMasterDetailList>`\n <div class=\"empty-state\">No matches</div>\n `\n )}\n </div>\n </div>\n`;"]}
@@ -0,0 +1,32 @@
1
+ import { FoundationElement } from '@ni/fast-foundation';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'ok-fv-master-detail-list-item': FvMasterDetailListItem;
5
+ }
6
+ }
7
+ /**
8
+ * A selectable master-detail list item with title, subtitle, and optional status content.
9
+ */
10
+ export declare class FvMasterDetailListItem extends FoundationElement {
11
+ titleText: string;
12
+ subtitle: string;
13
+ value: string;
14
+ compact: boolean;
15
+ selected: boolean;
16
+ statusColor: string;
17
+ statusLabel: string;
18
+ /** @internal */
19
+ hasStatusSlotContent: boolean;
20
+ /** @internal */
21
+ connectedCallback(): void;
22
+ /** @internal */
23
+ selectedChanged(): void;
24
+ /** @internal */
25
+ handleStatusSlotChange(event: Event): void;
26
+ /** @internal */
27
+ get hasStatus(): boolean;
28
+ /** @internal */
29
+ get fallbackStatusLabel(): string | null;
30
+ private syncSelectionAria;
31
+ }
32
+ export declare const fvMasterDetailListItemTag = "ok-fv-master-detail-list-item";
@@ -0,0 +1,86 @@
1
+ import { __decorate } from "tslib";
2
+ import { attr, observable } from '@ni/fast-element';
3
+ import { DesignSystem, FoundationElement } from '@ni/fast-foundation';
4
+ import { styles } from './styles';
5
+ import { template } from './template';
6
+ /**
7
+ * A selectable master-detail list item with title, subtitle, and optional status content.
8
+ */
9
+ export class FvMasterDetailListItem extends FoundationElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.titleText = '';
13
+ this.subtitle = '';
14
+ this.value = '';
15
+ this.compact = false;
16
+ this.selected = false;
17
+ this.statusColor = '';
18
+ this.statusLabel = '';
19
+ /** @internal */
20
+ this.hasStatusSlotContent = false;
21
+ }
22
+ /** @internal */
23
+ connectedCallback() {
24
+ super.connectedCallback();
25
+ this.setAttribute('role', 'option');
26
+ this.syncSelectionAria();
27
+ }
28
+ /** @internal */
29
+ selectedChanged() {
30
+ if (this.$fastController.isConnected) {
31
+ this.syncSelectionAria();
32
+ }
33
+ }
34
+ /** @internal */
35
+ handleStatusSlotChange(event) {
36
+ const slot = event.target;
37
+ this.hasStatusSlotContent = slot.assignedNodes({ flatten: true }).length > 0;
38
+ }
39
+ /** @internal */
40
+ get hasStatus() {
41
+ return this.hasStatusSlotContent || this.statusColor.trim().length > 0;
42
+ }
43
+ /** @internal */
44
+ get fallbackStatusLabel() {
45
+ if (this.hasStatusSlotContent || this.statusColor.trim().length === 0) {
46
+ return null;
47
+ }
48
+ const normalizedStatusLabel = this.statusLabel.trim();
49
+ return normalizedStatusLabel.length > 0 ? normalizedStatusLabel : null;
50
+ }
51
+ syncSelectionAria() {
52
+ this.setAttribute('aria-selected', String(this.selected));
53
+ }
54
+ }
55
+ __decorate([
56
+ attr({ attribute: 'title-text' })
57
+ ], FvMasterDetailListItem.prototype, "titleText", void 0);
58
+ __decorate([
59
+ attr
60
+ ], FvMasterDetailListItem.prototype, "subtitle", void 0);
61
+ __decorate([
62
+ attr
63
+ ], FvMasterDetailListItem.prototype, "value", void 0);
64
+ __decorate([
65
+ attr({ mode: 'boolean' })
66
+ ], FvMasterDetailListItem.prototype, "compact", void 0);
67
+ __decorate([
68
+ attr({ mode: 'boolean' })
69
+ ], FvMasterDetailListItem.prototype, "selected", void 0);
70
+ __decorate([
71
+ attr({ attribute: 'status-color' })
72
+ ], FvMasterDetailListItem.prototype, "statusColor", void 0);
73
+ __decorate([
74
+ attr({ attribute: 'status-label' })
75
+ ], FvMasterDetailListItem.prototype, "statusLabel", void 0);
76
+ __decorate([
77
+ observable
78
+ ], FvMasterDetailListItem.prototype, "hasStatusSlotContent", void 0);
79
+ const okFvMasterDetailListItem = FvMasterDetailListItem.compose({
80
+ baseName: 'fv-master-detail-list-item',
81
+ template,
82
+ styles
83
+ });
84
+ DesignSystem.getOrCreate().withPrefix('ok').register(okFvMasterDetailListItem());
85
+ export const fvMasterDetailListItemTag = 'ok-fv-master-detail-list-item';
86
+ //# sourceMappingURL=index.js.map