@ni/ok-components 1.10.3 → 1.11.1

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 (48) hide show
  1. package/dist/all-components-bundle.js +1125 -448
  2. package/dist/all-components-bundle.js.map +1 -1
  3. package/dist/all-components-bundle.min.js +5885 -5585
  4. package/dist/all-components-bundle.min.js.map +1 -1
  5. package/dist/custom-elements.json +1009 -0
  6. package/dist/custom-elements.md +140 -0
  7. package/dist/esm/fv/all-fv.d.ts +3 -0
  8. package/dist/esm/fv/all-fv.js +3 -0
  9. package/dist/esm/fv/all-fv.js.map +1 -1
  10. package/dist/esm/fv/bulk-edit-field/index.d.ts +40 -0
  11. package/dist/esm/fv/bulk-edit-field/index.js +120 -0
  12. package/dist/esm/fv/bulk-edit-field/index.js.map +1 -0
  13. package/dist/esm/fv/bulk-edit-field/styles.d.ts +1 -0
  14. package/dist/esm/fv/bulk-edit-field/styles.js +83 -0
  15. package/dist/esm/fv/bulk-edit-field/styles.js.map +1 -0
  16. package/dist/esm/fv/bulk-edit-field/template.d.ts +2 -0
  17. package/dist/esm/fv/bulk-edit-field/template.js +36 -0
  18. package/dist/esm/fv/bulk-edit-field/template.js.map +1 -0
  19. package/dist/esm/fv/bulk-edit-field/types.d.ts +7 -0
  20. package/dist/esm/fv/bulk-edit-field/types.js +7 -0
  21. package/dist/esm/fv/bulk-edit-field/types.js.map +1 -0
  22. package/dist/esm/fv/bulk-edit-state/index.d.ts +47 -0
  23. package/dist/esm/fv/bulk-edit-state/index.js +114 -0
  24. package/dist/esm/fv/bulk-edit-state/index.js.map +1 -0
  25. package/dist/esm/fv/edit-commit-bar/index.d.ts +32 -0
  26. package/dist/esm/fv/edit-commit-bar/index.js +92 -0
  27. package/dist/esm/fv/edit-commit-bar/index.js.map +1 -0
  28. package/dist/esm/fv/edit-commit-bar/styles.d.ts +1 -0
  29. package/dist/esm/fv/edit-commit-bar/styles.js +65 -0
  30. package/dist/esm/fv/edit-commit-bar/styles.js.map +1 -0
  31. package/dist/esm/fv/edit-commit-bar/template.d.ts +2 -0
  32. package/dist/esm/fv/edit-commit-bar/template.js +45 -0
  33. package/dist/esm/fv/edit-commit-bar/template.js.map +1 -0
  34. package/dist/esm/fv/edit-commit-bar/types.d.ts +4 -0
  35. package/dist/esm/fv/edit-commit-bar/types.js +2 -0
  36. package/dist/esm/fv/edit-commit-bar/types.js.map +1 -0
  37. package/dist/esm/fv/search-input/styles.js +4 -1
  38. package/dist/esm/fv/search-input/styles.js.map +1 -1
  39. package/dist/esm/fv/split-layout/index.d.ts +48 -0
  40. package/dist/esm/fv/split-layout/index.js +195 -0
  41. package/dist/esm/fv/split-layout/index.js.map +1 -0
  42. package/dist/esm/fv/split-layout/styles.d.ts +1 -0
  43. package/dist/esm/fv/split-layout/styles.js +42 -0
  44. package/dist/esm/fv/split-layout/styles.js.map +1 -0
  45. package/dist/esm/fv/split-layout/template.d.ts +2 -0
  46. package/dist/esm/fv/split-layout/template.js +24 -0
  47. package/dist/esm/fv/split-layout/template.js.map +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Framework-neutral state for editing common fields across selected records.
3
+ */
4
+ export class BulkEditState {
5
+ constructor(options) {
6
+ this.selected = new Set();
7
+ this.pending = new Map();
8
+ this.draft = new Map();
9
+ this.records = options.records;
10
+ this.id = options.id;
11
+ this.read = options.read;
12
+ }
13
+ get selectedIds() {
14
+ return [...this.selected];
15
+ }
16
+ get changes() {
17
+ return Object.fromEntries(this.pending);
18
+ }
19
+ get selectedRecords() {
20
+ return this.records.filter(record => this.selected.has(this.id(record)));
21
+ }
22
+ field(field) {
23
+ if (this.pending.has(field)) {
24
+ const value = this.pending.get(field);
25
+ return { value, mixed: false, pending: true, willClear: value === '' };
26
+ }
27
+ const values = this.selectedRecords.map(record => this.read(record, field));
28
+ const value = values[0] ?? '';
29
+ const mixed = values.some(candidate => candidate !== value);
30
+ return { value: this.draft.get(field) ?? (mixed ? '' : value), mixed, pending: false, willClear: false };
31
+ }
32
+ edit(field, value) {
33
+ if (this.selected.size === 0) {
34
+ return;
35
+ }
36
+ if (value.trim() !== '' && this.selectedRecords.some(record => this.read(record, field) !== value)) {
37
+ this.setPending(field, value);
38
+ }
39
+ else {
40
+ this.pending.delete(field);
41
+ }
42
+ this.draft.set(field, value);
43
+ }
44
+ clear(field) {
45
+ if (this.selected.size === 0) {
46
+ return;
47
+ }
48
+ if (this.selectedRecords.some(record => this.read(record, field) !== '')) {
49
+ this.setPending(field, '');
50
+ }
51
+ else {
52
+ this.pending.delete(field);
53
+ }
54
+ this.draft.set(field, '');
55
+ }
56
+ resetField(field) {
57
+ this.pending.delete(field);
58
+ this.draft.delete(field);
59
+ }
60
+ revert() {
61
+ this.pending.clear();
62
+ this.draft.clear();
63
+ }
64
+ isSelection(ids) {
65
+ const next = new Set(ids);
66
+ return next.size === this.selected.size && [...next].every(id => this.selected.has(id));
67
+ }
68
+ visibleSelection(visibleIds) {
69
+ return visibleIds.filter(id => this.selected.has(id));
70
+ }
71
+ mergeVisible(visibleIds, selectedVisibleIds, additive = false) {
72
+ const visible = new Set(visibleIds);
73
+ const merged = additive
74
+ ? new Set(this.selected)
75
+ : new Set([...this.selected].filter(id => !visible.has(id)));
76
+ selectedVisibleIds.filter(id => visible.has(id)).forEach(id => merged.add(id));
77
+ return [...merged];
78
+ }
79
+ select(ids) {
80
+ if (this.isSelection(ids)) {
81
+ return;
82
+ }
83
+ this.selected = new Set(ids);
84
+ this.revert();
85
+ }
86
+ createCommit() {
87
+ const changes = this.changes;
88
+ const fields = [...this.pending.keys()];
89
+ return {
90
+ selectedIds: this.selectedIds,
91
+ changes,
92
+ affectedRecords: this.selectedRecords.filter(record => fields.some(field => this.read(record, field) !== changes[field]))
93
+ };
94
+ }
95
+ commitSucceeded(updatedRecords) {
96
+ if (updatedRecords) {
97
+ this.records = updatedRecords;
98
+ }
99
+ this.revert();
100
+ }
101
+ setPending(field, value) {
102
+ if (typeof field !== 'symbol') {
103
+ for (const existing of this.pending.keys()) {
104
+ if (typeof existing !== 'symbol'
105
+ && typeof existing !== typeof field
106
+ && String(existing) === String(field)) {
107
+ throw new TypeError('Numeric and string field keys that map to the same object key cannot both be pending.');
108
+ }
109
+ }
110
+ }
111
+ this.pending.set(field, value);
112
+ }
113
+ }
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fv/bulk-edit-state/index.ts"],"names":[],"mappings":"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","sourcesContent":["export type RecordId = string;\nexport type PendingChanges<TField extends PropertyKey> = {\n [Field in TField]?: string;\n};\n\nexport interface BulkEditFieldValue {\n value: string;\n mixed: boolean;\n pending: boolean;\n willClear: boolean;\n}\n\nexport interface BulkEditCommit<TRecord, TField extends PropertyKey> {\n selectedIds: readonly RecordId[];\n changes: Readonly<PendingChanges<TField>>;\n affectedRecords: readonly TRecord[];\n}\n\nexport interface BulkEditStateOptions<TRecord, TField extends PropertyKey> {\n records: readonly TRecord[];\n id: (record: TRecord) => RecordId;\n read: (record: TRecord, field: TField) => string;\n}\n\n/**\n * Framework-neutral state for editing common fields across selected records.\n */\nexport class BulkEditState<TRecord, TField extends PropertyKey> {\n private records: readonly TRecord[];\n private readonly id: (record: TRecord) => RecordId;\n private readonly read: (record: TRecord, field: TField) => string;\n private selected = new Set<RecordId>();\n private readonly pending = new Map<TField, string>();\n private readonly draft = new Map<TField, string>();\n\n public constructor(options: BulkEditStateOptions<TRecord, TField>) {\n this.records = options.records;\n this.id = options.id;\n this.read = options.read;\n }\n\n public get selectedIds(): readonly RecordId[] {\n return [...this.selected];\n }\n\n public get changes(): Readonly<PendingChanges<TField>> {\n return Object.fromEntries(this.pending) as PendingChanges<TField>;\n }\n\n public get selectedRecords(): readonly TRecord[] {\n return this.records.filter(record => this.selected.has(this.id(record)));\n }\n\n public field(field: TField): BulkEditFieldValue {\n if (this.pending.has(field)) {\n const value = this.pending.get(field)!;\n return { value, mixed: false, pending: true, willClear: value === '' };\n }\n\n const values = this.selectedRecords.map(record => this.read(record, field));\n const value = values[0] ?? '';\n const mixed = values.some(candidate => candidate !== value);\n return { value: this.draft.get(field) ?? (mixed ? '' : value), mixed, pending: false, willClear: false };\n }\n\n public edit(field: TField, value: string): void {\n if (this.selected.size === 0) {\n return;\n }\n if (value.trim() !== '' && this.selectedRecords.some(record => this.read(record, field) !== value)) {\n this.setPending(field, value);\n } else {\n this.pending.delete(field);\n }\n this.draft.set(field, value);\n }\n\n public clear(field: TField): void {\n if (this.selected.size === 0) {\n return;\n }\n if (this.selectedRecords.some(record => this.read(record, field) !== '')) {\n this.setPending(field, '');\n } else {\n this.pending.delete(field);\n }\n this.draft.set(field, '');\n }\n\n public resetField(field: TField): void {\n this.pending.delete(field);\n this.draft.delete(field);\n }\n\n public revert(): void {\n this.pending.clear();\n this.draft.clear();\n }\n\n public isSelection(ids: readonly RecordId[]): boolean {\n const next = new Set(ids);\n return next.size === this.selected.size && [...next].every(id => this.selected.has(id));\n }\n\n public visibleSelection(visibleIds: readonly RecordId[]): readonly RecordId[] {\n return visibleIds.filter(id => this.selected.has(id));\n }\n\n public mergeVisible(\n visibleIds: readonly RecordId[],\n selectedVisibleIds: readonly RecordId[],\n additive = false\n ): readonly RecordId[] {\n const visible = new Set(visibleIds);\n const merged = additive\n ? new Set(this.selected)\n : new Set([...this.selected].filter(id => !visible.has(id)));\n selectedVisibleIds.filter(id => visible.has(id)).forEach(id => merged.add(id));\n return [...merged];\n }\n\n public select(ids: readonly RecordId[]): void {\n if (this.isSelection(ids)) {\n return;\n }\n this.selected = new Set(ids);\n this.revert();\n }\n\n public createCommit(): BulkEditCommit<TRecord, TField> {\n const changes = this.changes;\n const fields = [...this.pending.keys()];\n return {\n selectedIds: this.selectedIds,\n changes,\n affectedRecords: this.selectedRecords.filter(\n record => fields.some(field => this.read(record, field) !== changes[field])\n )\n };\n }\n\n public commitSucceeded(updatedRecords?: readonly TRecord[]): void {\n if (updatedRecords) {\n this.records = updatedRecords;\n }\n this.revert();\n }\n\n private setPending(field: TField, value: string): void {\n if (typeof field !== 'symbol') {\n for (const existing of this.pending.keys()) {\n if (typeof existing !== 'symbol'\n && typeof existing !== typeof field\n && String(existing) === String(field)) {\n throw new TypeError('Numeric and string field keys that map to the same object key cannot both be pending.');\n }\n }\n }\n this.pending.set(field, value);\n }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { FoundationElement } from '@ni/fast-foundation';
2
+ import type { BannerToggleEventDetail } from '@ni/nimble-components/dist/esm/banner/types';
3
+ import type { CommitMessage } from './types';
4
+ declare global {
5
+ interface HTMLElementTagNameMap {
6
+ 'ok-fv-edit-commit-bar': FvEditCommitBar;
7
+ }
8
+ }
9
+ /**
10
+ * Heading, pending-change summary, actions, and feedback for an edit pane.
11
+ */
12
+ export declare class FvEditCommitBar extends FoundationElement {
13
+ heading: string;
14
+ changeCount: number;
15
+ affectedRowCount: number;
16
+ hiddenAffectedRowCount: number;
17
+ saveDisabled: boolean;
18
+ revertDisabled: boolean;
19
+ actionsHidden: boolean;
20
+ hideEmptySummary: boolean;
21
+ message: CommitMessage | undefined;
22
+ /** @internal */
23
+ get summary(): string;
24
+ /** @internal */
25
+ save(): boolean;
26
+ /** @internal */
27
+ revert(): boolean;
28
+ /** @internal */
29
+ handleBannerToggle(event: CustomEvent<BannerToggleEventDetail>): boolean;
30
+ }
31
+ export declare const fvEditCommitBarTag = "ok-fv-edit-commit-bar";
32
+ export type { CommitMessage };
@@ -0,0 +1,92 @@
1
+ import { __decorate } from "tslib";
2
+ import { attr, nullableNumberConverter, observable, volatile } from '@ni/fast-element';
3
+ import { DesignSystem, FoundationElement } from '@ni/fast-foundation';
4
+ import { styles } from './styles';
5
+ import { template } from './template';
6
+ /**
7
+ * Heading, pending-change summary, actions, and feedback for an edit pane.
8
+ */
9
+ export class FvEditCommitBar extends FoundationElement {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.heading = '';
13
+ this.changeCount = 0;
14
+ this.affectedRowCount = 0;
15
+ this.hiddenAffectedRowCount = 0;
16
+ this.saveDisabled = false;
17
+ this.revertDisabled = false;
18
+ this.actionsHidden = false;
19
+ this.hideEmptySummary = false;
20
+ }
21
+ /** @internal */
22
+ get summary() {
23
+ if (this.changeCount === 0) {
24
+ return 'No pending changes';
25
+ }
26
+ const changes = `${this.changeCount} unsaved ${this.changeCount === 1 ? 'change' : 'changes'}`;
27
+ const rows = `${this.affectedRowCount} ${this.affectedRowCount === 1 ? 'row' : 'rows'}`;
28
+ const hidden = this.hiddenAffectedRowCount > 0
29
+ ? ` (${this.hiddenAffectedRowCount} hidden)`
30
+ : '';
31
+ return `${changes} in ${rows}${hidden}`;
32
+ }
33
+ /** @internal */
34
+ save() {
35
+ if (!this.saveDisabled) {
36
+ this.$emit('save');
37
+ }
38
+ return true;
39
+ }
40
+ /** @internal */
41
+ revert() {
42
+ if (!this.revertDisabled) {
43
+ this.$emit('revert');
44
+ }
45
+ return true;
46
+ }
47
+ /** @internal */
48
+ handleBannerToggle(event) {
49
+ if (!event.detail.newState) {
50
+ this.$emit('dismiss-message');
51
+ }
52
+ return true;
53
+ }
54
+ }
55
+ __decorate([
56
+ attr
57
+ ], FvEditCommitBar.prototype, "heading", void 0);
58
+ __decorate([
59
+ attr({ attribute: 'change-count', converter: nullableNumberConverter })
60
+ ], FvEditCommitBar.prototype, "changeCount", void 0);
61
+ __decorate([
62
+ attr({ attribute: 'affected-row-count', converter: nullableNumberConverter })
63
+ ], FvEditCommitBar.prototype, "affectedRowCount", void 0);
64
+ __decorate([
65
+ attr({ attribute: 'hidden-affected-row-count', converter: nullableNumberConverter })
66
+ ], FvEditCommitBar.prototype, "hiddenAffectedRowCount", void 0);
67
+ __decorate([
68
+ attr({ attribute: 'save-disabled', mode: 'boolean' })
69
+ ], FvEditCommitBar.prototype, "saveDisabled", void 0);
70
+ __decorate([
71
+ attr({ attribute: 'revert-disabled', mode: 'boolean' })
72
+ ], FvEditCommitBar.prototype, "revertDisabled", void 0);
73
+ __decorate([
74
+ attr({ attribute: 'actions-hidden', mode: 'boolean' })
75
+ ], FvEditCommitBar.prototype, "actionsHidden", void 0);
76
+ __decorate([
77
+ attr({ attribute: 'hide-empty-summary', mode: 'boolean' })
78
+ ], FvEditCommitBar.prototype, "hideEmptySummary", void 0);
79
+ __decorate([
80
+ observable
81
+ ], FvEditCommitBar.prototype, "message", void 0);
82
+ __decorate([
83
+ volatile
84
+ ], FvEditCommitBar.prototype, "summary", null);
85
+ const okFvEditCommitBar = FvEditCommitBar.compose({
86
+ baseName: 'fv-edit-commit-bar',
87
+ template,
88
+ styles
89
+ });
90
+ DesignSystem.getOrCreate().withPrefix('ok').register(okFvEditCommitBar());
91
+ export const fvEditCommitBarTag = 'ok-fv-edit-commit-bar';
92
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fv/edit-commit-bar/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { attr, nullableNumberConverter, observable, volatile } from '@ni/fast-element';\nimport { DesignSystem, FoundationElement } from '@ni/fast-foundation';\nimport type { BannerToggleEventDetail } from '@ni/nimble-components/dist/esm/banner/types';\nimport { styles } from './styles';\nimport { template } from './template';\nimport type { CommitMessage } from './types';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ok-fv-edit-commit-bar': FvEditCommitBar;\n }\n}\n\n/**\n * Heading, pending-change summary, actions, and feedback for an edit pane.\n */\nexport class FvEditCommitBar extends FoundationElement {\n @attr\n public heading = '';\n\n @attr({ attribute: 'change-count', converter: nullableNumberConverter })\n public changeCount = 0;\n\n @attr({ attribute: 'affected-row-count', converter: nullableNumberConverter })\n public affectedRowCount = 0;\n\n @attr({ attribute: 'hidden-affected-row-count', converter: nullableNumberConverter })\n public hiddenAffectedRowCount = 0;\n\n @attr({ attribute: 'save-disabled', mode: 'boolean' })\n public saveDisabled = false;\n\n @attr({ attribute: 'revert-disabled', mode: 'boolean' })\n public revertDisabled = false;\n\n @attr({ attribute: 'actions-hidden', mode: 'boolean' })\n public actionsHidden = false;\n\n @attr({ attribute: 'hide-empty-summary', mode: 'boolean' })\n public hideEmptySummary = false;\n\n @observable\n public message: CommitMessage | undefined;\n\n /** @internal */\n @volatile\n public get summary(): string {\n if (this.changeCount === 0) {\n return 'No pending changes';\n }\n const changes = `${this.changeCount} unsaved ${this.changeCount === 1 ? 'change' : 'changes'}`;\n const rows = `${this.affectedRowCount} ${this.affectedRowCount === 1 ? 'row' : 'rows'}`;\n const hidden = this.hiddenAffectedRowCount > 0\n ? ` (${this.hiddenAffectedRowCount} hidden)`\n : '';\n return `${changes} in ${rows}${hidden}`;\n }\n\n /** @internal */\n public save(): boolean {\n if (!this.saveDisabled) {\n this.$emit('save');\n }\n return true;\n }\n\n /** @internal */\n public revert(): boolean {\n if (!this.revertDisabled) {\n this.$emit('revert');\n }\n return true;\n }\n\n /** @internal */\n public handleBannerToggle(event: CustomEvent<BannerToggleEventDetail>): boolean {\n if (!event.detail.newState) {\n this.$emit('dismiss-message');\n }\n return true;\n }\n}\n\nconst okFvEditCommitBar = FvEditCommitBar.compose({\n baseName: 'fv-edit-commit-bar',\n template,\n styles\n});\n\nDesignSystem.getOrCreate().withPrefix('ok').register(okFvEditCommitBar());\nexport const fvEditCommitBarTag = 'ok-fv-edit-commit-bar';\nexport type { CommitMessage };\n"]}
@@ -0,0 +1 @@
1
+ export declare const styles: import("@ni/fast-element").ElementStyles;
@@ -0,0 +1,65 @@
1
+ import { css } from '@ni/fast-element';
2
+ import { bodyFont, bodyFontColor, dividerBackgroundColor, standardPadding } from '@ni/nimble-components/dist/esm/theme-provider/design-tokens';
3
+ import { display } from '../../utilities/style/display';
4
+ export const styles = css `
5
+ ${display('block')}
6
+
7
+ :host {
8
+ color: ${bodyFontColor};
9
+ font: ${bodyFont};
10
+ container-type: inline-size;
11
+ }
12
+
13
+ .bar {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ gap: ${standardPadding};
18
+ padding: ${standardPadding};
19
+ border-block-end: 1px solid ${dividerBackgroundColor};
20
+ }
21
+
22
+ .text {
23
+ flex: 1 1 auto;
24
+ min-width: 0;
25
+ }
26
+
27
+ .heading {
28
+ display: flex;
29
+ align-items: center;
30
+ gap: ${standardPadding};
31
+ }
32
+
33
+ h2 {
34
+ flex: 1 1 auto;
35
+ min-width: 0;
36
+ margin: 0;
37
+ font: inherit;
38
+ font-weight: 600;
39
+ }
40
+
41
+ .summary {
42
+ margin-block-start: 4px;
43
+ }
44
+
45
+ .actions {
46
+ display: flex;
47
+ flex: 0 0 auto;
48
+ gap: ${standardPadding};
49
+ }
50
+
51
+ @container (max-width: 420px) {
52
+ .bar {
53
+ flex-wrap: wrap;
54
+ }
55
+
56
+ .text {
57
+ flex-basis: 100%;
58
+ }
59
+
60
+ .actions {
61
+ margin-inline-start: auto;
62
+ }
63
+ }
64
+ `;
65
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../src/fv/edit-commit-bar/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EACH,QAAQ,EACR,aAAa,EACb,sBAAsB,EACtB,eAAe,EAClB,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAExD,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;MACnB,OAAO,CAAC,OAAO,CAAC;;;iBAGL,aAAa;gBACd,QAAQ;;;;;;;;eAQT,eAAe;mBACX,eAAe;sCACI,sBAAsB;;;;;;;;;;;eAW7C,eAAe;;;;;;;;;;;;;;;;;;eAkBf,eAAe;;;;;;;;;;;;;;;;CAgB7B,CAAC","sourcesContent":["import { css } from '@ni/fast-element';\nimport {\n bodyFont,\n bodyFontColor,\n dividerBackgroundColor,\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 ${display('block')}\n\n :host {\n color: ${bodyFontColor};\n font: ${bodyFont};\n container-type: inline-size;\n }\n\n .bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: ${standardPadding};\n padding: ${standardPadding};\n border-block-end: 1px solid ${dividerBackgroundColor};\n }\n\n .text {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .heading {\n display: flex;\n align-items: center;\n gap: ${standardPadding};\n }\n\n h2 {\n flex: 1 1 auto;\n min-width: 0;\n margin: 0;\n font: inherit;\n font-weight: 600;\n }\n\n .summary {\n margin-block-start: 4px;\n }\n\n .actions {\n display: flex;\n flex: 0 0 auto;\n gap: ${standardPadding};\n }\n\n @container (max-width: 420px) {\n .bar {\n flex-wrap: wrap;\n }\n\n .text {\n flex-basis: 100%;\n }\n\n .actions {\n margin-inline-start: auto;\n }\n }\n`;\n"]}
@@ -0,0 +1,2 @@
1
+ import type { FvEditCommitBar } from '.';
2
+ export declare const template: import("@ni/fast-element").ViewTemplate<FvEditCommitBar, any>;
@@ -0,0 +1,45 @@
1
+ import { html, when } from '@ni/fast-element';
2
+ import { bannerTag } from '@ni/nimble-components/dist/esm/banner';
3
+ import { buttonTag } from '@ni/nimble-components/dist/esm/button';
4
+ import { iconArrowPartialRotateLeftTag } from '@ni/nimble-components/dist/esm/icons/arrow-partial-rotate-left';
5
+ import { iconFloppyDiskTag } from '@ni/nimble-components/dist/esm/icons/floppy-disk';
6
+ export const template = html `
7
+ ${when(x => x.message !== undefined, html `
8
+ <${bannerTag}
9
+ :open="${x => x.message !== undefined}"
10
+ title-hidden
11
+ severity="${x => x.message?.severity}"
12
+ aria-live="${x => (x.message?.severity === 'error' ? 'assertive' : 'polite')}"
13
+ @toggle="${(x, c) => x.handleBannerToggle(c.event)}"
14
+ >${x => x.message?.text}</${bannerTag}>
15
+ `)}
16
+ <div class="bar">
17
+ <div class="text">
18
+ <div class="heading">
19
+ <h2>${x => x.heading}</h2>
20
+ <slot name="heading-actions"></slot>
21
+ </div>
22
+ ${when(x => !x.hideEmptySummary || x.changeCount > 0, html `
23
+ <div class="summary" role="status" aria-live="polite" aria-atomic="true">
24
+ ${x => x.summary}
25
+ </div>
26
+ `)}
27
+ </div>
28
+ ${when(x => !x.actionsHidden, html `
29
+ <div class="actions">
30
+ <${buttonTag}
31
+ appearance="ghost"
32
+ ?disabled="${x => x.revertDisabled}"
33
+ @click="${x => x.revert()}"
34
+ ><${iconArrowPartialRotateLeftTag} slot="start"></${iconArrowPartialRotateLeftTag}>Revert</${buttonTag}>
35
+ <${buttonTag}
36
+ appearance="block"
37
+ appearance-variant="accent"
38
+ ?disabled="${x => x.saveDisabled}"
39
+ @click="${x => x.save()}"
40
+ ><${iconFloppyDiskTag} slot="start"></${iconFloppyDiskTag}>Save</${buttonTag}>
41
+ </div>
42
+ `)}
43
+ </div>
44
+ `;
45
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../../../src/fv/edit-commit-bar/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAElE,OAAO,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAClE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gEAAgE,CAAC;AAC/G,OAAO,EAAE,iBAAiB,EAAE,MAAM,kDAAkD,CAAC;AAGrF,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAiB;MACvC,IAAI,CACF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,EAC5B,IAAI,CAAiB;eACd,SAAS;yBACC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS;;4BAEzB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ;6BACvB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;2BACjE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAA6C,CAAC;eAC3F,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,KAAK,SAAS;SACxC,CACJ;;;;sBAIiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;;;cAGtB,IAAI,CACF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,WAAW,GAAG,CAAC,EAC7C,IAAI,CAAiB;;0BAEX,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;;iBAEvB,CACJ;;UAEH,IAAI,CACF,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,EACrB,IAAI,CAAiB;;uBAEV,SAAS;;qCAEK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc;kCACxB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE;wBACzB,6BAA6B,mBAAmB,6BAA6B,YAAY,SAAS;uBACnG,SAAS;;;qCAGK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY;kCACtB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;wBACvB,iBAAiB,mBAAmB,iBAAiB,UAAU,SAAS;;aAEnF,CACJ;;CAER,CAAC","sourcesContent":["import { html, when } from '@ni/fast-element';\nimport { bannerTag } from '@ni/nimble-components/dist/esm/banner';\nimport type { BannerToggleEventDetail } from '@ni/nimble-components/dist/esm/banner/types';\nimport { buttonTag } from '@ni/nimble-components/dist/esm/button';\nimport { iconArrowPartialRotateLeftTag } from '@ni/nimble-components/dist/esm/icons/arrow-partial-rotate-left';\nimport { iconFloppyDiskTag } from '@ni/nimble-components/dist/esm/icons/floppy-disk';\nimport type { FvEditCommitBar } from '.';\n\nexport const template = html<FvEditCommitBar>`\n ${when(\n x => x.message !== undefined,\n html<FvEditCommitBar>`\n <${bannerTag}\n :open=\"${x => x.message !== undefined}\"\n title-hidden\n severity=\"${x => x.message?.severity}\"\n aria-live=\"${x => (x.message?.severity === 'error' ? 'assertive' : 'polite')}\"\n @toggle=\"${(x, c) => x.handleBannerToggle(c.event as CustomEvent<BannerToggleEventDetail>)}\"\n >${x => x.message?.text}</${bannerTag}>\n `\n )}\n <div class=\"bar\">\n <div class=\"text\">\n <div class=\"heading\">\n <h2>${x => x.heading}</h2>\n <slot name=\"heading-actions\"></slot>\n </div>\n ${when(\n x => !x.hideEmptySummary || x.changeCount > 0,\n html<FvEditCommitBar>`\n <div class=\"summary\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n ${x => x.summary}\n </div>\n `\n )}\n </div>\n ${when(\n x => !x.actionsHidden,\n html<FvEditCommitBar>`\n <div class=\"actions\">\n <${buttonTag}\n appearance=\"ghost\"\n ?disabled=\"${x => x.revertDisabled}\"\n @click=\"${x => x.revert()}\"\n ><${iconArrowPartialRotateLeftTag} slot=\"start\"></${iconArrowPartialRotateLeftTag}>Revert</${buttonTag}>\n <${buttonTag}\n appearance=\"block\"\n appearance-variant=\"accent\"\n ?disabled=\"${x => x.saveDisabled}\"\n @click=\"${x => x.save()}\"\n ><${iconFloppyDiskTag} slot=\"start\"></${iconFloppyDiskTag}>Save</${buttonTag}>\n </div>\n `\n )}\n </div>\n`;\n"]}
@@ -0,0 +1,4 @@
1
+ export interface CommitMessage {
2
+ severity: 'information' | 'error';
3
+ text: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/fv/edit-commit-bar/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface CommitMessage {\n severity: 'information' | 'error';\n text: string;\n}\n"]}
@@ -41,7 +41,7 @@ export const styles = css `
41
41
  position: absolute;
42
42
  inset-inline: 0;
43
43
  inset-block-end: calc(-1 * ${borderWidth});
44
- border-bottom: calc(${borderWidth} + 1px) solid ${borderHoverColor};
44
+ border-bottom: ${borderWidth} solid ${borderHoverColor};
45
45
  transform: scaleX(0);
46
46
  transform-origin: center;
47
47
  transition:
@@ -135,12 +135,15 @@ export const styles = css `
135
135
  border-bottom-color: ${borderHoverColor};
136
136
  }
137
137
 
138
+ :host([appearance='block']) .search-input-container:hover::after,
138
139
  :host([appearance='underline']) .search-input-container:hover::after {
140
+ border-bottom-width: calc(${borderWidth} + 1px);
139
141
  border-bottom-color: ${borderHoverColor};
140
142
  }
141
143
 
142
144
  :host([appearance='frameless']) .search-input-container:hover::after {
143
145
  transform: scaleX(1);
146
+ border-bottom-width: calc(${borderWidth} + 1px);
144
147
  border-bottom-color: ${borderHoverColor};
145
148
  }
146
149
  }
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../src/fv/search-input/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,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,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,cAAc,CAAC;;;8DAG6B,eAAe;6DAChB,aAAa;uHAC6C,QAAQ,MAAM,YAAY;yHACxB,QAAQ;iEAChE,qBAAqB;;;sBAGhE,aAAa;oBACf,QAAQ;qBACP,aAAa;;;;;;;;;sBASZ,WAAW;;;;;+BAKF,UAAU;6BACZ,UAAU;mCACJ,UAAU;;;;;;;yCAOJ,WAAW;kCAClB,WAAW,iBAAiB,gBAAgB;;;;4BAIlD,UAAU;sCACA,UAAU;;;;;;;;;;;;qBAY3B,oBAAoB;;cAE3B,SAAS,CAAC,iBAAiB,KAAK,oBAAoB;;;;;;;;;;;;;;;;;;;;;;qBAsB7C,oBAAoB;;;;;;;;;;;;;;;;;;;;;cAqB3B,SAAS,CAAC,iBAAiB;;;;;;;;qCAQJ,qBAAqB;;;;;;;;;;;0BAWhC,cAAc;;;;4BAIZ,gBAAgB;gCACZ,WAAW,IAAI,gBAAgB;;;;;mCAK5B,gBAAgB;;;;mCAIhB,gBAAgB;;;;;mCAKhB,gBAAgB;;;;;;;;;;uBAU5B,WAAW,UAAU,gBAAgB;;;;;4BAKhC,gBAAgB;gCACZ,WAAW,IAAI,gBAAgB;;;;;mCAK5B,gBAAgB;;;;mCAIhB,gBAAgB;;;;;mCAKhB,gBAAgB;;;CAGlD,CAAC","sourcesContent":["import { css } from '@ni/fast-element';\nimport {\n bodyFont,\n bodyFontColor,\n borderHoverColor,\n borderRgbPartialColor,\n borderWidth,\n controlHeight,\n fillHoverColor,\n iconColor,\n iconSize,\n mediumPadding,\n placeholderFontColor,\n smallPadding,\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, active, disabled, top;\n\n @layer base {\n ${display('inline-block')}\n\n :host {\n --ni-private-ok-fv-search-input-inline-padding: ${standardPadding};\n --ni-private-ok-fv-search-input-leading-inset: ${mediumPadding};\n --ni-private-ok-fv-search-input-leading-space: calc(var(--ni-private-ok-fv-search-input-leading-inset) + ${iconSize} + ${smallPadding});\n --ni-private-ok-fv-search-input-trailing-space: calc(var(--ni-private-ok-fv-search-input-inline-padding) + ${iconSize});\n --ni-private-ok-fv-search-input-border-color: rgba(${borderRgbPartialColor}, 0.3);\n --ni-private-ok-fv-search-input-border-radius: 0px;\n min-width: 120px;\n height: ${controlHeight};\n font: ${bodyFont};\n color: ${bodyFontColor};\n }\n\n .search-input-container {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n height: 100%;\n border: ${borderWidth} solid transparent;\n border-radius: var(--ni-private-ok-fv-search-input-border-radius);\n color: inherit;\n background-color: transparent;\n transition:\n border-color ${smallDelay} ease-in-out,\n box-shadow ${smallDelay} ease-in-out,\n background-color ${smallDelay} ease-in-out;\n }\n\n .search-input-container::after {\n content: '';\n position: absolute;\n inset-inline: 0;\n inset-block-end: calc(-1 * ${borderWidth});\n border-bottom: calc(${borderWidth} + 1px) solid ${borderHoverColor};\n transform: scaleX(0);\n transform-origin: center;\n transition:\n transform ${smallDelay} ease-in-out,\n border-bottom-color ${smallDelay} ease-in-out;\n pointer-events: none;\n }\n\n .search-input-icon {\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n top: 50%;\n inset-inline-start: var(--ni-private-ok-fv-search-input-leading-inset);\n transform: translateY(-50%);\n color: ${placeholderFontColor};\n pointer-events: none;\n ${iconColor.cssCustomProperty}: ${placeholderFontColor};\n }\n\n .search-input {\n -webkit-appearance: none;\n appearance: none;\n display: block;\n flex: 1 1 auto;\n min-width: 0;\n width: 100%;\n height: 100%;\n padding: 0 var(--ni-private-ok-fv-search-input-trailing-space) 0 var(--ni-private-ok-fv-search-input-leading-space);\n font: inherit;\n line-height: normal;\n color: inherit;\n border: none;\n outline: none;\n border-radius: 0;\n background: transparent;\n }\n\n .search-input::placeholder {\n color: ${placeholderFontColor};\n }\n\n .search-input-clear {\n -webkit-appearance: none;\n appearance: none;\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n top: 50%;\n inset-inline-end: 3px;\n height: calc(100% - 6px);\n aspect-ratio: 1;\n padding: 0;\n transform: translateY(-50%);\n color: inherit;\n border: none;\n border-radius: 2px;\n background: transparent;\n cursor: pointer;\n ${iconColor.cssCustomProperty}: currentColor;\n }\n\n :host([appearance='outline']) .search-input-container {\n border-color: var(--ni-private-ok-fv-search-input-border-color);\n }\n\n :host([appearance='block']) .search-input-container {\n background-color: rgba(${borderRgbPartialColor}, 0.1);\n }\n\n :host([appearance='underline']) .search-input-container::after {\n transform: scaleX(1);\n border-bottom-color: var(--ni-private-ok-fv-search-input-border-color);\n }\n }\n\n @layer hover {\n .search-input-clear:hover {\n background: ${fillHoverColor};\n }\n\n :host([appearance='outline']) .search-input-container:hover {\n border-color: ${borderHoverColor};\n box-shadow: 0 0 0 ${borderWidth} ${borderHoverColor} inset;\n }\n\n :host([appearance='block']) .search-input-container:hover::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='underline']) .search-input-container:hover::after {\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='frameless']) .search-input-container:hover::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n }\n\n @layer focusVisible {\n .search-input:focus-visible {\n outline: none;\n }\n\n .search-input-clear:focus-visible {\n outline: ${borderWidth} solid ${borderHoverColor};\n outline-offset: -1px;\n }\n\n :host([appearance='outline']) .search-input-container:focus-within {\n border-color: ${borderHoverColor};\n box-shadow: 0 0 0 ${borderWidth} ${borderHoverColor} inset;\n }\n\n :host([appearance='block']) .search-input-container:focus-within::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='underline']) .search-input-container:focus-within::after {\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='frameless']) .search-input-container:focus-within::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n }\n`;"]}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../../src/fv/search-input/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,aAAa,EACb,cAAc,EACd,SAAS,EACT,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,YAAY,EACZ,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,cAAc,CAAC;;;8DAG6B,eAAe;6DAChB,aAAa;uHAC6C,QAAQ,MAAM,YAAY;yHACxB,QAAQ;iEAChE,qBAAqB;;;sBAGhE,aAAa;oBACf,QAAQ;qBACP,aAAa;;;;;;;;;sBASZ,WAAW;;;;;+BAKF,UAAU;6BACZ,UAAU;mCACJ,UAAU;;;;;;;yCAOJ,WAAW;6BACvB,WAAW,UAAU,gBAAgB;;;;4BAItC,UAAU;sCACA,UAAU;;;;;;;;;;;;qBAY3B,oBAAoB;;cAE3B,SAAS,CAAC,iBAAiB,KAAK,oBAAoB;;;;;;;;;;;;;;;;;;;;;;qBAsB7C,oBAAoB;;;;;;;;;;;;;;;;;;;;;cAqB3B,SAAS,CAAC,iBAAiB;;;;;;;;qCAQJ,qBAAqB;;;;;;;;;;;0BAWhC,cAAc;;;;4BAIZ,gBAAgB;gCACZ,WAAW,IAAI,gBAAgB;;;;;mCAK5B,gBAAgB;;;;;wCAKX,WAAW;mCAChB,gBAAgB;;;;;wCAKX,WAAW;mCAChB,gBAAgB;;;;;;;;;;uBAU5B,WAAW,UAAU,gBAAgB;;;;;4BAKhC,gBAAgB;gCACZ,WAAW,IAAI,gBAAgB;;;;;mCAK5B,gBAAgB;;;;mCAIhB,gBAAgB;;;;;mCAKhB,gBAAgB;;;CAGlD,CAAC","sourcesContent":["import { css } from '@ni/fast-element';\nimport {\n bodyFont,\n bodyFontColor,\n borderHoverColor,\n borderRgbPartialColor,\n borderWidth,\n controlHeight,\n fillHoverColor,\n iconColor,\n iconSize,\n mediumPadding,\n placeholderFontColor,\n smallPadding,\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, active, disabled, top;\n\n @layer base {\n ${display('inline-block')}\n\n :host {\n --ni-private-ok-fv-search-input-inline-padding: ${standardPadding};\n --ni-private-ok-fv-search-input-leading-inset: ${mediumPadding};\n --ni-private-ok-fv-search-input-leading-space: calc(var(--ni-private-ok-fv-search-input-leading-inset) + ${iconSize} + ${smallPadding});\n --ni-private-ok-fv-search-input-trailing-space: calc(var(--ni-private-ok-fv-search-input-inline-padding) + ${iconSize});\n --ni-private-ok-fv-search-input-border-color: rgba(${borderRgbPartialColor}, 0.3);\n --ni-private-ok-fv-search-input-border-radius: 0px;\n min-width: 120px;\n height: ${controlHeight};\n font: ${bodyFont};\n color: ${bodyFontColor};\n }\n\n .search-input-container {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n height: 100%;\n border: ${borderWidth} solid transparent;\n border-radius: var(--ni-private-ok-fv-search-input-border-radius);\n color: inherit;\n background-color: transparent;\n transition:\n border-color ${smallDelay} ease-in-out,\n box-shadow ${smallDelay} ease-in-out,\n background-color ${smallDelay} ease-in-out;\n }\n\n .search-input-container::after {\n content: '';\n position: absolute;\n inset-inline: 0;\n inset-block-end: calc(-1 * ${borderWidth});\n border-bottom: ${borderWidth} solid ${borderHoverColor};\n transform: scaleX(0);\n transform-origin: center;\n transition:\n transform ${smallDelay} ease-in-out,\n border-bottom-color ${smallDelay} ease-in-out;\n pointer-events: none;\n }\n\n .search-input-icon {\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n top: 50%;\n inset-inline-start: var(--ni-private-ok-fv-search-input-leading-inset);\n transform: translateY(-50%);\n color: ${placeholderFontColor};\n pointer-events: none;\n ${iconColor.cssCustomProperty}: ${placeholderFontColor};\n }\n\n .search-input {\n -webkit-appearance: none;\n appearance: none;\n display: block;\n flex: 1 1 auto;\n min-width: 0;\n width: 100%;\n height: 100%;\n padding: 0 var(--ni-private-ok-fv-search-input-trailing-space) 0 var(--ni-private-ok-fv-search-input-leading-space);\n font: inherit;\n line-height: normal;\n color: inherit;\n border: none;\n outline: none;\n border-radius: 0;\n background: transparent;\n }\n\n .search-input::placeholder {\n color: ${placeholderFontColor};\n }\n\n .search-input-clear {\n -webkit-appearance: none;\n appearance: none;\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n top: 50%;\n inset-inline-end: 3px;\n height: calc(100% - 6px);\n aspect-ratio: 1;\n padding: 0;\n transform: translateY(-50%);\n color: inherit;\n border: none;\n border-radius: 2px;\n background: transparent;\n cursor: pointer;\n ${iconColor.cssCustomProperty}: currentColor;\n }\n\n :host([appearance='outline']) .search-input-container {\n border-color: var(--ni-private-ok-fv-search-input-border-color);\n }\n\n :host([appearance='block']) .search-input-container {\n background-color: rgba(${borderRgbPartialColor}, 0.1);\n }\n\n :host([appearance='underline']) .search-input-container::after {\n transform: scaleX(1);\n border-bottom-color: var(--ni-private-ok-fv-search-input-border-color);\n }\n }\n\n @layer hover {\n .search-input-clear:hover {\n background: ${fillHoverColor};\n }\n\n :host([appearance='outline']) .search-input-container:hover {\n border-color: ${borderHoverColor};\n box-shadow: 0 0 0 ${borderWidth} ${borderHoverColor} inset;\n }\n\n :host([appearance='block']) .search-input-container:hover::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='block']) .search-input-container:hover::after,\n :host([appearance='underline']) .search-input-container:hover::after {\n border-bottom-width: calc(${borderWidth} + 1px);\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='frameless']) .search-input-container:hover::after {\n transform: scaleX(1);\n border-bottom-width: calc(${borderWidth} + 1px);\n border-bottom-color: ${borderHoverColor};\n }\n }\n\n @layer focusVisible {\n .search-input:focus-visible {\n outline: none;\n }\n\n .search-input-clear:focus-visible {\n outline: ${borderWidth} solid ${borderHoverColor};\n outline-offset: -1px;\n }\n\n :host([appearance='outline']) .search-input-container:focus-within {\n border-color: ${borderHoverColor};\n box-shadow: 0 0 0 ${borderWidth} ${borderHoverColor} inset;\n }\n\n :host([appearance='block']) .search-input-container:focus-within::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='underline']) .search-input-container:focus-within::after {\n border-bottom-color: ${borderHoverColor};\n }\n\n :host([appearance='frameless']) .search-input-container:focus-within::after {\n transform: scaleX(1);\n border-bottom-color: ${borderHoverColor};\n }\n }\n`;"]}
@@ -0,0 +1,48 @@
1
+ import { FoundationElement } from '@ni/fast-foundation';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'ok-fv-split-layout': FvSplitLayout;
5
+ }
6
+ }
7
+ /**
8
+ * A full-height, resizable two-pane layout.
9
+ */
10
+ export declare class FvSplitLayout extends FoundationElement {
11
+ position: number;
12
+ min: number;
13
+ max: number;
14
+ minSecondaryPixels: number;
15
+ collapsed: boolean;
16
+ step: number;
17
+ primaryPaneId: string;
18
+ secondaryPaneId: string;
19
+ /** @internal */
20
+ availableWidth: number;
21
+ private readonly resizeObserver;
22
+ private requestedPosition;
23
+ private applyingConstrainedPosition;
24
+ private requestedPositionResetScheduled;
25
+ private positionChangeCallbackVersion;
26
+ constructor();
27
+ connectedCallback(): void;
28
+ disconnectedCallback(): void;
29
+ positionChanged(): void;
30
+ minChanged(): void;
31
+ maxChanged(): void;
32
+ minSecondaryPixelsChanged(): void;
33
+ collapsedChanged(): void;
34
+ /** @internal */
35
+ get effectiveMin(): number;
36
+ /** @internal */
37
+ get effectiveMax(): number;
38
+ /** @internal */
39
+ get gridTemplateColumns(): string;
40
+ /** @internal */
41
+ handleSplitterInput(event: Event): boolean;
42
+ /** @internal */
43
+ handleSplitterChange(event: Event): boolean;
44
+ private constrainPosition;
45
+ private resetRequestedPositionAfterSynchronousUpdates;
46
+ private get effectiveMinSecondaryPixels();
47
+ }
48
+ export declare const fvSplitLayoutTag = "ok-fv-split-layout";