@memberjunction/ng-ui-components 6.2.0-edge.0 → 6.2.0-edge.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.
- package/README.md +35 -9
- package/dist/lib/a11y/named-control.base.d.ts +91 -0
- package/dist/lib/a11y/named-control.base.d.ts.map +1 -0
- package/dist/lib/a11y/named-control.base.js +121 -0
- package/dist/lib/a11y/named-control.base.js.map +1 -0
- package/dist/lib/a11y/unnamed-control-guard.d.ts +52 -0
- package/dist/lib/a11y/unnamed-control-guard.d.ts.map +1 -0
- package/dist/lib/a11y/unnamed-control-guard.js +94 -0
- package/dist/lib/a11y/unnamed-control-guard.js.map +1 -0
- package/dist/lib/accordion/accordion.component.d.ts +16 -4
- package/dist/lib/accordion/accordion.component.d.ts.map +1 -1
- package/dist/lib/accordion/accordion.component.js +36 -12
- package/dist/lib/accordion/accordion.component.js.map +1 -1
- package/dist/lib/applied-filters/applied-filters.component.js.map +1 -1
- package/dist/lib/button/button.directive.d.ts +34 -6
- package/dist/lib/button/button.directive.d.ts.map +1 -1
- package/dist/lib/button/button.directive.js +85 -25
- package/dist/lib/button/button.directive.js.map +1 -1
- package/dist/lib/card-grid/card-grid.component.d.ts +3 -1
- package/dist/lib/card-grid/card-grid.component.d.ts.map +1 -1
- package/dist/lib/card-grid/card-grid.component.js +13 -9
- package/dist/lib/card-grid/card-grid.component.js.map +1 -1
- package/dist/lib/clickable/clickable.directive.d.ts +11 -3
- package/dist/lib/clickable/clickable.directive.d.ts.map +1 -1
- package/dist/lib/clickable/clickable.directive.js +25 -5
- package/dist/lib/clickable/clickable.directive.js.map +1 -1
- package/dist/lib/combobox/combobox.component.d.ts +44 -3
- package/dist/lib/combobox/combobox.component.d.ts.map +1 -1
- package/dist/lib/combobox/combobox.component.js +135 -51
- package/dist/lib/combobox/combobox.component.js.map +1 -1
- package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts +6 -0
- package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts.map +1 -1
- package/dist/lib/confirm-dialog/confirm-dialog.component.js +16 -4
- package/dist/lib/confirm-dialog/confirm-dialog.component.js.map +1 -1
- package/dist/lib/datepicker/datepicker.component.d.ts +25 -2
- package/dist/lib/datepicker/datepicker.component.d.ts.map +1 -1
- package/dist/lib/datepicker/datepicker.component.js +98 -42
- package/dist/lib/datepicker/datepicker.component.js.map +1 -1
- package/dist/lib/dialog/dialog.component.d.ts +4 -0
- package/dist/lib/dialog/dialog.component.d.ts.map +1 -1
- package/dist/lib/dialog/dialog.component.js +12 -4
- package/dist/lib/dialog/dialog.component.js.map +1 -1
- package/dist/lib/dialog/dialog.service.js.map +1 -1
- package/dist/lib/dropdown/dropdown.component.d.ts +19 -44
- package/dist/lib/dropdown/dropdown.component.d.ts.map +1 -1
- package/dist/lib/dropdown/dropdown.component.js +37 -76
- package/dist/lib/dropdown/dropdown.component.js.map +1 -1
- package/dist/lib/dropdown/dropdown.scss +0 -16
- package/dist/lib/filter-panel/filter-panel.component.d.ts +8 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts.map +1 -1
- package/dist/lib/filter-panel/filter-panel.component.js +25 -9
- package/dist/lib/filter-panel/filter-panel.component.js.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts +15 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.js +36 -9
- package/dist/lib/numeric-input/numeric-input.component.js.map +1 -1
- package/dist/lib/page-search/page-search.component.d.ts +32 -3
- package/dist/lib/page-search/page-search.component.d.ts.map +1 -1
- package/dist/lib/page-search/page-search.component.js +68 -12
- package/dist/lib/page-search/page-search.component.js.map +1 -1
- package/dist/lib/switch/switch.component.d.ts +22 -1
- package/dist/lib/switch/switch.component.d.ts.map +1 -1
- package/dist/lib/switch/switch.component.js +50 -16
- package/dist/lib/switch/switch.component.js.map +1 -1
- package/dist/lib/tabs/tab-chrome-guard.d.ts +2 -0
- package/dist/lib/tabs/tab-chrome-guard.d.ts.map +1 -1
- package/dist/lib/tabs/tab-chrome-guard.js +5 -1
- package/dist/lib/tabs/tab-chrome-guard.js.map +1 -1
- package/dist/lib/window/window.component.d.ts +10 -0
- package/dist/lib/window/window.component.d.ts.map +1 -1
- package/dist/lib/window/window.component.js +27 -7
- package/dist/lib/window/window.component.js.map +1 -1
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts +10 -0
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts.map +1 -1
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.js +27 -7
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAOvE,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,IAAI,EAAE,eAAe,CAAC;IACtB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzF;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,2DAA2D;AAC3D,KAAK,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBA0Ia,sBAAsB;IACxB,MAAM,EAAE,iBAAiB,EAAE,CAAM;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IACrC,SAAS,EAAE,OAAO,CAAQ;IAC1B,UAAU,EAAE,MAAM,CAAmB;IAEpC,YAAY,wCAA+C;IAC3D,KAAK,qBAA4B;IAEpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAKlD,0EAA0E;IACnE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAQnF,iFAAiF;IAC1E,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"filter-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAOvE,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,IAAI,EAAE,eAAe,CAAC;IACtB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzF;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,2DAA2D;AAC3D,KAAK,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBA0Ia,sBAAsB;IACxB,MAAM,EAAE,iBAAiB,EAAE,CAAM;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IACrC,SAAS,EAAE,OAAO,CAAQ;IAC1B,UAAU,EAAE,MAAM,CAAmB;IAEpC,YAAY,wCAA+C;IAC3D,KAAK,qBAA4B;IAEpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIrC,wCAAwC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAKlD,wCAAwC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAIlD,0EAA0E;IACnE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAQnF,4CAA4C;IACrC,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAInF,iFAAiF;IAC1E,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAgB/E,2CAA2C;IACpC,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;yCA5DpE,sBAAsB;2CAAtB,sBAAsB;CA+DlC"}
|
|
@@ -106,28 +106,40 @@ export class MJFilterPanelComponent {
|
|
|
106
106
|
ResetLabel = 'Reset filters';
|
|
107
107
|
ValuesChange = new EventEmitter();
|
|
108
108
|
Reset = new EventEmitter();
|
|
109
|
-
|
|
109
|
+
GetValue(key) {
|
|
110
110
|
return this.Values?.[key];
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
/** @deprecated Use {@link GetValue}. */
|
|
113
|
+
getValue(key) {
|
|
114
|
+
return this.GetValue(key);
|
|
115
|
+
}
|
|
116
|
+
SetValue(key, value) {
|
|
113
117
|
this.Values = { ...this.Values, [key]: value };
|
|
114
118
|
this.ValuesChange.emit(this.Values);
|
|
115
119
|
}
|
|
120
|
+
/** @deprecated Use {@link SetValue}. */
|
|
121
|
+
setValue(key, value) {
|
|
122
|
+
return this.SetValue(key, value);
|
|
123
|
+
}
|
|
116
124
|
/** Whether a chip option is currently active (handles single + multi). */
|
|
117
|
-
|
|
125
|
+
IsChipActive(field, optValue) {
|
|
118
126
|
if (field.multi) {
|
|
119
|
-
const current = this.
|
|
127
|
+
const current = this.GetValue(field.key);
|
|
120
128
|
return Array.isArray(current) && current.includes(optValue);
|
|
121
129
|
}
|
|
122
|
-
return this.
|
|
130
|
+
return this.GetValue(field.key) === optValue;
|
|
131
|
+
}
|
|
132
|
+
/** @deprecated Use {@link IsChipActive}. */
|
|
133
|
+
isChipActive(field, optValue) {
|
|
134
|
+
return this.IsChipActive(field, optValue);
|
|
123
135
|
}
|
|
124
136
|
/** Chip click: replace (single-select) or toggle in/out of the array (multi). */
|
|
125
|
-
|
|
137
|
+
OnChipClick(field, optValue) {
|
|
126
138
|
if (!field.multi) {
|
|
127
|
-
this.
|
|
139
|
+
this.SetValue(field.key, optValue);
|
|
128
140
|
return;
|
|
129
141
|
}
|
|
130
|
-
const current = this.
|
|
142
|
+
const current = this.GetValue(field.key);
|
|
131
143
|
const next = Array.isArray(current) ? [...current] : [];
|
|
132
144
|
const idx = next.indexOf(optValue);
|
|
133
145
|
if (idx >= 0) {
|
|
@@ -136,7 +148,11 @@ export class MJFilterPanelComponent {
|
|
|
136
148
|
else {
|
|
137
149
|
next.push(optValue);
|
|
138
150
|
}
|
|
139
|
-
this.
|
|
151
|
+
this.SetValue(field.key, next);
|
|
152
|
+
}
|
|
153
|
+
/** @deprecated Use {@link OnChipClick}. */
|
|
154
|
+
onChipClick(field, optValue) {
|
|
155
|
+
return this.OnChipClick(field, optValue);
|
|
140
156
|
}
|
|
141
157
|
static ɵfac = function MJFilterPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJFilterPanelComponent)(); };
|
|
142
158
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJFilterPanelComponent, selectors: [["mj-filter-panel"]], inputs: { Fields: "Fields", Values: "Values", ShowReset: "ShowReset", ResetLabel: "ResetLabel" }, outputs: { ValuesChange: "ValuesChange", Reset: "Reset" }, ngContentSelectors: _c0, decls: 6, vars: 1, consts: [[1, "mj-filter-panel"], [1, "mj-filter-panel-body"], [3, "Label", "Icon"], [1, "mj-filter-panel-footer"], ["type", "text", 1, "mj-filter-panel-text-input", 3, "value", "placeholder"], ["TextField", "text", "ValueField", "value", 3, "Data", "ValuePrimitive", "Filterable", "Placeholder", "ngModel"], [1, "mj-filter-panel-chip-group"], ["type", "text", 1, "mj-filter-panel-text-input", 3, "input", "value", "placeholder"], ["TextField", "text", "ValueField", "value", 3, "ngModelChange", "Data", "ValuePrimitive", "Filterable", "Placeholder", "ngModel"], [3, "Label", "Icon", "Active"], [3, "Clicked", "Label", "Icon", "Active"], ["type", "button", 1, "mj-filter-panel-reset", 3, "click"], [1, "fa-solid", "fa-rotate-left"]], template: function MJFilterPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-panel.component.js","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MJDropdownComponent } from '../dropdown/dropdown.component';\nimport { MJFilterChipComponent } from '../filter-chip/filter-chip.component';\nimport { MJFilterFieldComponent } from '../filter-field/filter-field.component';\n\n/** Field types supported natively by <mj-filter-panel>. */\nexport type FilterFieldType = 'text' | 'dropdown' | 'chips';\n\n/** Per-field config understood by <mj-filter-panel>. */\nexport interface FilterFieldConfig {\n /** State key in the Values record. */\n key: string;\n /** Field type — drives which widget is rendered. */\n type: FilterFieldType;\n /** Display label. */\n label: string;\n /** Optional Font Awesome icon class (e.g. 'fa-solid fa-folder'). */\n icon?: string;\n /** Placeholder for text inputs / dropdowns. */\n placeholder?: string;\n /** Dropdown options (when type === 'dropdown'). Each option needs text + value. */\n options?: { text: string; value: string | number | boolean | null }[];\n /** Whether the dropdown should show an internal search box. */\n filterable?: boolean;\n /** Chip-group options (when type === 'chips'). */\n chipOptions?: { text: string; value: string | number | boolean | null; icon?: string }[];\n /**\n * For `type === 'chips'` only. When `true`, the chip group is multi-select:\n * the field's value is an **array** of selected option values and clicking a\n * chip toggles it in/out. When absent/false (default), the group is\n * single-select (value is the chosen option value, click replaces).\n */\n multi?: boolean;\n}\n\n/** Option value type shared by dropdown + chip options. */\ntype FilterOptionValue = string | number | boolean | null;\n\n/**\n * mj-filter-panel — Single centralized filter panel for all dashboards.\n *\n * Config-driven: pass an array of `FilterFieldConfig` plus a `Values` record;\n * the panel renders each field using the appropriate widget (text input,\n * `<mj-dropdown>`, or chip group), keeps everything visually consistent, and\n * emits state changes via `(ValuesChange)`.\n *\n * For widgets not covered by the config schema (tree-dropdown, date pickers,\n * etc.), project `<mj-filter-field>` elements as content — they render below\n * the config-driven fields with identical chrome.\n *\n * Example:\n * ```html\n * <mj-filter-panel\n * [Fields]=\"filterFields\"\n * [(Values)]=\"filterValues\"\n * (Reset)=\"onReset()\">\n *\n * <!-- escape hatch for custom widgets -->\n * <mj-filter-field Label=\"Category\" Icon=\"fa-solid fa-folder\">\n * <mj-tree-dropdown ...></mj-tree-dropdown>\n * </mj-filter-field>\n * </mj-filter-panel>\n * ```\n */\n@Component({\n selector: 'mj-filter-panel',\n standalone: true,\n imports: [CommonModule, FormsModule, MJDropdownComponent, MJFilterChipComponent, MJFilterFieldComponent],\n template: `\n <div class=\"mj-filter-panel\">\n <div class=\"mj-filter-panel-body\">\n @for (field of Fields; track field.key) {\n <mj-filter-field [Label]=\"field.label\" [Icon]=\"field.icon ?? null\">\n @switch (field.type) {\n @case ('text') {\n <input\n type=\"text\"\n class=\"mj-filter-panel-text-input\"\n [value]=\"getValue(field.key) ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n (input)=\"setValue(field.key, $any($event.target).value)\" />\n }\n @case ('dropdown') {\n <mj-dropdown\n [Data]=\"field.options ?? []\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"!!field.filterable\"\n [Placeholder]=\"field.placeholder ?? ''\"\n [ngModel]=\"getValue(field.key)\"\n (ngModelChange)=\"setValue(field.key, $event)\">\n </mj-dropdown>\n }\n @case ('chips') {\n <div class=\"mj-filter-panel-chip-group\">\n @for (opt of field.chipOptions ?? []; track opt.value) {\n <mj-filter-chip\n [Label]=\"opt.text\"\n [Icon]=\"opt.icon ?? null\"\n [Active]=\"isChipActive(field, opt.value)\"\n (Clicked)=\"onChipClick(field, opt.value)\">\n </mj-filter-chip>\n }\n </div>\n }\n }\n </mj-filter-field>\n }\n\n <!-- Escape hatch for custom field widgets (e.g. mj-tree-dropdown, date pickers) -->\n <ng-content></ng-content>\n </div>\n\n @if (ShowReset) {\n <div class=\"mj-filter-panel-footer\">\n <button type=\"button\" class=\"mj-filter-panel-reset\" (click)=\"Reset.emit()\">\n <i class=\"fa-solid fa-rotate-left\"></i> {{ ResetLabel }}\n </button>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n }\n\n .mj-filter-panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-body {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-text-input {\n width: 100%;\n padding: 7px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .mj-filter-panel-text-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n\n .mj-filter-panel-text-input::placeholder {\n color: var(--mj-text-muted);\n }\n\n .mj-filter-panel-chip-group {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .mj-filter-panel-footer {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .mj-filter-panel-reset {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n }\n\n .mj-filter-panel-reset:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n\n .mj-filter-panel-reset i {\n font-size: 11px;\n }\n `]\n})\nexport class MJFilterPanelComponent {\n @Input() Fields: FilterFieldConfig[] = [];\n @Input() Values: Record<string, unknown> = {};\n @Input() ShowReset: boolean = true;\n @Input() ResetLabel: string = 'Reset filters';\n\n @Output() ValuesChange = new EventEmitter<Record<string, unknown>>();\n @Output() Reset = new EventEmitter<void>();\n\n public getValue(key: string): unknown {\n return this.Values?.[key];\n }\n\n public setValue(key: string, value: unknown): void {\n this.Values = { ...this.Values, [key]: value };\n this.ValuesChange.emit(this.Values);\n }\n\n /** Whether a chip option is currently active (handles single + multi). */\n public isChipActive(field: FilterFieldConfig, optValue: FilterOptionValue): boolean {\n if (field.multi) {\n const current = this.getValue(field.key);\n return Array.isArray(current) && current.includes(optValue);\n }\n return this.getValue(field.key) === optValue;\n }\n\n /** Chip click: replace (single-select) or toggle in/out of the array (multi). */\n public onChipClick(field: FilterFieldConfig, optValue: FilterOptionValue): void {\n if (!field.multi) {\n this.setValue(field.key, optValue);\n return;\n }\n const current = this.getValue(field.key);\n const next: FilterOptionValue[] = Array.isArray(current) ? [...current] : [];\n const idx = next.indexOf(optValue);\n if (idx >= 0) {\n next.splice(idx, 1);\n } else {\n next.push(optValue);\n }\n this.setValue(field.key, next);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"filter-panel.component.js","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MJDropdownComponent } from '../dropdown/dropdown.component';\nimport { MJFilterChipComponent } from '../filter-chip/filter-chip.component';\nimport { MJFilterFieldComponent } from '../filter-field/filter-field.component';\n\n/** Field types supported natively by <mj-filter-panel>. */\nexport type FilterFieldType = 'text' | 'dropdown' | 'chips';\n\n/** Per-field config understood by <mj-filter-panel>. */\nexport interface FilterFieldConfig {\n /** State key in the Values record. */\n key: string;\n /** Field type — drives which widget is rendered. */\n type: FilterFieldType;\n /** Display label. */\n label: string;\n /** Optional Font Awesome icon class (e.g. 'fa-solid fa-folder'). */\n icon?: string;\n /** Placeholder for text inputs / dropdowns. */\n placeholder?: string;\n /** Dropdown options (when type === 'dropdown'). Each option needs text + value. */\n options?: { text: string; value: string | number | boolean | null }[];\n /** Whether the dropdown should show an internal search box. */\n filterable?: boolean;\n /** Chip-group options (when type === 'chips'). */\n chipOptions?: { text: string; value: string | number | boolean | null; icon?: string }[];\n /**\n * For `type === 'chips'` only. When `true`, the chip group is multi-select:\n * the field's value is an **array** of selected option values and clicking a\n * chip toggles it in/out. When absent/false (default), the group is\n * single-select (value is the chosen option value, click replaces).\n */\n multi?: boolean;\n}\n\n/** Option value type shared by dropdown + chip options. */\ntype FilterOptionValue = string | number | boolean | null;\n\n/**\n * mj-filter-panel — Single centralized filter panel for all dashboards.\n *\n * Config-driven: pass an array of `FilterFieldConfig` plus a `Values` record;\n * the panel renders each field using the appropriate widget (text input,\n * `<mj-dropdown>`, or chip group), keeps everything visually consistent, and\n * emits state changes via `(ValuesChange)`.\n *\n * For widgets not covered by the config schema (tree-dropdown, date pickers,\n * etc.), project `<mj-filter-field>` elements as content — they render below\n * the config-driven fields with identical chrome.\n *\n * Example:\n * ```html\n * <mj-filter-panel\n * [Fields]=\"filterFields\"\n * [(Values)]=\"filterValues\"\n * (Reset)=\"onReset()\">\n *\n * <!-- escape hatch for custom widgets -->\n * <mj-filter-field Label=\"Category\" Icon=\"fa-solid fa-folder\">\n * <mj-tree-dropdown ...></mj-tree-dropdown>\n * </mj-filter-field>\n * </mj-filter-panel>\n * ```\n */\n@Component({\n selector: 'mj-filter-panel',\n standalone: true,\n imports: [CommonModule, FormsModule, MJDropdownComponent, MJFilterChipComponent, MJFilterFieldComponent],\n template: `\n <div class=\"mj-filter-panel\">\n <div class=\"mj-filter-panel-body\">\n @for (field of Fields; track field.key) {\n <mj-filter-field [Label]=\"field.label\" [Icon]=\"field.icon ?? null\">\n @switch (field.type) {\n @case ('text') {\n <input\n type=\"text\"\n class=\"mj-filter-panel-text-input\"\n [value]=\"getValue(field.key) ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n (input)=\"setValue(field.key, $any($event.target).value)\" />\n }\n @case ('dropdown') {\n <mj-dropdown\n [Data]=\"field.options ?? []\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"!!field.filterable\"\n [Placeholder]=\"field.placeholder ?? ''\"\n [ngModel]=\"getValue(field.key)\"\n (ngModelChange)=\"setValue(field.key, $event)\">\n </mj-dropdown>\n }\n @case ('chips') {\n <div class=\"mj-filter-panel-chip-group\">\n @for (opt of field.chipOptions ?? []; track opt.value) {\n <mj-filter-chip\n [Label]=\"opt.text\"\n [Icon]=\"opt.icon ?? null\"\n [Active]=\"isChipActive(field, opt.value)\"\n (Clicked)=\"onChipClick(field, opt.value)\">\n </mj-filter-chip>\n }\n </div>\n }\n }\n </mj-filter-field>\n }\n\n <!-- Escape hatch for custom field widgets (e.g. mj-tree-dropdown, date pickers) -->\n <ng-content></ng-content>\n </div>\n\n @if (ShowReset) {\n <div class=\"mj-filter-panel-footer\">\n <button type=\"button\" class=\"mj-filter-panel-reset\" (click)=\"Reset.emit()\">\n <i class=\"fa-solid fa-rotate-left\"></i> {{ ResetLabel }}\n </button>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n }\n\n .mj-filter-panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-body {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-text-input {\n width: 100%;\n padding: 7px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .mj-filter-panel-text-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n\n .mj-filter-panel-text-input::placeholder {\n color: var(--mj-text-muted);\n }\n\n .mj-filter-panel-chip-group {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .mj-filter-panel-footer {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .mj-filter-panel-reset {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n }\n\n .mj-filter-panel-reset:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n\n .mj-filter-panel-reset i {\n font-size: 11px;\n }\n `]\n})\nexport class MJFilterPanelComponent {\n @Input() Fields: FilterFieldConfig[] = [];\n @Input() Values: Record<string, unknown> = {};\n @Input() ShowReset: boolean = true;\n @Input() ResetLabel: string = 'Reset filters';\n\n @Output() ValuesChange = new EventEmitter<Record<string, unknown>>();\n @Output() Reset = new EventEmitter<void>();\n\n public GetValue(key: string): unknown {\n return this.Values?.[key];\n }\n\n /** @deprecated Use {@link GetValue}. */\n public getValue(key: string): unknown {\n return this.GetValue(key);\n }\n\n public SetValue(key: string, value: unknown): void {\n this.Values = { ...this.Values, [key]: value };\n this.ValuesChange.emit(this.Values);\n }\n\n /** @deprecated Use {@link SetValue}. */\n public setValue(key: string, value: unknown): void {\n return this.SetValue(key, value);\n }\n\n /** Whether a chip option is currently active (handles single + multi). */\n public IsChipActive(field: FilterFieldConfig, optValue: FilterOptionValue): boolean {\n if (field.multi) {\n const current = this.GetValue(field.key);\n return Array.isArray(current) && current.includes(optValue);\n }\n return this.GetValue(field.key) === optValue;\n }\n\n /** @deprecated Use {@link IsChipActive}. */\n public isChipActive(field: FilterFieldConfig, optValue: FilterOptionValue): boolean {\n return this.IsChipActive(field, optValue);\n }\n\n /** Chip click: replace (single-select) or toggle in/out of the array (multi). */\n public OnChipClick(field: FilterFieldConfig, optValue: FilterOptionValue): void {\n if (!field.multi) {\n this.SetValue(field.key, optValue);\n return;\n }\n const current = this.GetValue(field.key);\n const next: FilterOptionValue[] = Array.isArray(current) ? [...current] : [];\n const idx = next.indexOf(optValue);\n if (idx >= 0) {\n next.splice(idx, 1);\n } else {\n next.push(optValue);\n }\n this.SetValue(field.key, next);\n }\n\n /** @deprecated Use {@link OnChipClick}. */\n public onChipClick(field: FilterFieldConfig, optValue: FilterOptionValue): void {\n return this.OnChipClick(field, optValue);\n }\n}\n"]}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
+
import { AfterViewInit } from '@angular/core';
|
|
1
2
|
import { ControlValueAccessor } from '@angular/forms';
|
|
3
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
2
4
|
import * as i0 from "@angular/core";
|
|
3
5
|
/**
|
|
4
6
|
* mj-numeric-input — Numeric input with min/max/step. Replaces `<kendo-numerictextbox>`.
|
|
7
|
+
*
|
|
8
|
+
* A spinbutton with no accessible name announces as "spin button, blank" (WCAG 2.1 4.1.2). Use
|
|
9
|
+
* {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,
|
|
10
|
+
* {@link MJNamedControlBase.AriaLabel} when none does. The control here is a real `<input>`, so
|
|
11
|
+
* {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```html
|
|
15
|
+
* <mj-numeric-input AriaLabel="Quantity" [(ngModel)]="quantity" [Min]="0" [Max]="100" />
|
|
16
|
+
* ```
|
|
5
17
|
*/
|
|
6
|
-
export declare class MJNumericInputComponent implements ControlValueAccessor {
|
|
18
|
+
export declare class MJNumericInputComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit {
|
|
7
19
|
Min: number | null;
|
|
8
20
|
Max: number | null;
|
|
9
21
|
Step: number;
|
|
@@ -19,6 +31,7 @@ export declare class MJNumericInputComponent implements ControlValueAccessor {
|
|
|
19
31
|
get Disabled(): boolean;
|
|
20
32
|
Placeholder: string;
|
|
21
33
|
readonly hostClass = true;
|
|
34
|
+
private numericInputEl;
|
|
22
35
|
/** The rendered `[disabled]` state — true when EITHER source says so. Assign via `syncDisabled()`. */
|
|
23
36
|
IsDisabled: boolean;
|
|
24
37
|
private disabledInput;
|
|
@@ -38,6 +51,7 @@ export declare class MJNumericInputComponent implements ControlValueAccessor {
|
|
|
38
51
|
private internalValue;
|
|
39
52
|
private onChange;
|
|
40
53
|
private onTouched;
|
|
54
|
+
ngAfterViewInit(): void;
|
|
41
55
|
OnInput(event: Event): void;
|
|
42
56
|
OnBlur(): void;
|
|
43
57
|
writeValue(value: number | null): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numeric-input.component.d.ts","sourceRoot":"","sources":["../../../src/lib/numeric-input/numeric-input.component.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"numeric-input.component.d.ts","sourceRoot":"","sources":["../../../src/lib/numeric-input/numeric-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EASd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAqB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAGhE;;;;;;;;;;;;GAYG;AACH,qBAgBa,uBAAwB,SAAQ,kBAAmB,YAAW,oBAAoB,EAAE,aAAa;IACnG,GAAG,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC1B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC1B,IAAI,EAAE,MAAM,CAAK;IACjB,MAAM,EAAE,MAAM,CAAM;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxC;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAsD;IACjF,IAAI,QAAQ,IAAI,OAAO,CAA+B;IAC7C,WAAW,SAAM;IACkB,QAAQ,CAAC,SAAS,QAAQ;IAC3C,OAAO,CAAC,cAAc,CAA2C;IAE5F,sGAAsG;IACtG,UAAU,UAAS;IACnB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,GAAG,CAA6B;IAExC;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAOpB,YAAY,EAAE,MAAM,GAAG,MAAM,CAAM;IACnC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,SAAS,CAAwB;IAEzC,eAAe,IAAI,IAAI;IAEvB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAU3B,MAAM,IAAI,IAAI;IAEd,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IACtC,gBAAgB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAC1D,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IACvC,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;IAE3C,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,aAAa;yCAxEV,uBAAuB;2CAAvB,uBAAuB;CA4EnC"}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import { Component,
|
|
1
|
+
import { ChangeDetectorRef, Component, HostBinding, Input, ViewChild, forwardRef, inject } from '@angular/core';
|
|
2
2
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
3
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
4
|
+
import { WarnIfUnnamed } from '../a11y/unnamed-control-guard';
|
|
3
5
|
import * as i0 from "@angular/core";
|
|
6
|
+
const _c0 = ["numericInput"];
|
|
4
7
|
/**
|
|
5
8
|
* mj-numeric-input — Numeric input with min/max/step. Replaces `<kendo-numerictextbox>`.
|
|
9
|
+
*
|
|
10
|
+
* A spinbutton with no accessible name announces as "spin button, blank" (WCAG 2.1 4.1.2). Use
|
|
11
|
+
* {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,
|
|
12
|
+
* {@link MJNamedControlBase.AriaLabel} when none does. The control here is a real `<input>`, so
|
|
13
|
+
* {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```html
|
|
17
|
+
* <mj-numeric-input AriaLabel="Quantity" [(ngModel)]="quantity" [Min]="0" [Max]="100" />
|
|
18
|
+
* ```
|
|
6
19
|
*/
|
|
7
|
-
export class MJNumericInputComponent {
|
|
20
|
+
export class MJNumericInputComponent extends MJNamedControlBase {
|
|
8
21
|
Min = null;
|
|
9
22
|
Max = null;
|
|
10
23
|
Step = 1;
|
|
@@ -20,6 +33,7 @@ export class MJNumericInputComponent {
|
|
|
20
33
|
get Disabled() { return this.disabledInput; }
|
|
21
34
|
Placeholder = '';
|
|
22
35
|
hostClass = true;
|
|
36
|
+
numericInputEl;
|
|
23
37
|
/** The rendered `[disabled]` state — true when EITHER source says so. Assign via `syncDisabled()`. */
|
|
24
38
|
IsDisabled = false;
|
|
25
39
|
disabledInput = false;
|
|
@@ -45,6 +59,7 @@ export class MJNumericInputComponent {
|
|
|
45
59
|
internalValue = null;
|
|
46
60
|
onChange = () => { };
|
|
47
61
|
onTouched = () => { };
|
|
62
|
+
ngAfterViewInit() { WarnIfUnnamed(this.numericInputEl?.nativeElement, 'mj-numeric-input'); }
|
|
48
63
|
OnInput(event) {
|
|
49
64
|
const raw = event.target.value;
|
|
50
65
|
if (raw === '' || raw === '-') {
|
|
@@ -82,16 +97,21 @@ export class MJNumericInputComponent {
|
|
|
82
97
|
}
|
|
83
98
|
this.DisplayValue = this.Decimals != null ? this.internalValue.toFixed(this.Decimals) : this.internalValue;
|
|
84
99
|
}
|
|
85
|
-
static ɵfac = function MJNumericInputComponent_Factory(__ngFactoryType__) { return
|
|
86
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJNumericInputComponent, selectors: [["mj-numeric-input"]],
|
|
100
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵMJNumericInputComponent_BaseFactory; return function MJNumericInputComponent_Factory(__ngFactoryType__) { return (ɵMJNumericInputComponent_BaseFactory || (ɵMJNumericInputComponent_BaseFactory = i0.ɵɵgetInheritedFactory(MJNumericInputComponent)))(__ngFactoryType__ || MJNumericInputComponent); }; })();
|
|
101
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJNumericInputComponent, selectors: [["mj-numeric-input"]], viewQuery: function MJNumericInputComponent_Query(rf, ctx) { if (rf & 1) {
|
|
102
|
+
i0.ɵɵviewQuery(_c0, 5);
|
|
103
|
+
} if (rf & 2) {
|
|
104
|
+
let _t;
|
|
105
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.numericInputEl = _t.first);
|
|
106
|
+
} }, hostVars: 2, hostBindings: function MJNumericInputComponent_HostBindings(rf, ctx) { if (rf & 2) {
|
|
87
107
|
i0.ɵɵclassProp("mj-numeric-input-host", ctx.hostClass);
|
|
88
|
-
} }, inputs: { Min: "Min", Max: "Max", Step: "Step", Format: "Format", Decimals: "Decimals", Disabled: "Disabled", Placeholder: "Placeholder" }, features: [i0.ɵɵProvidersFeature([{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJNumericInputComponent), multi: true }])], decls:
|
|
89
|
-
i0.ɵɵdomElementStart(0, "input", 0);
|
|
108
|
+
} }, inputs: { Min: "Min", Max: "Max", Step: "Step", Format: "Format", Decimals: "Decimals", Disabled: "Disabled", Placeholder: "Placeholder" }, features: [i0.ɵɵProvidersFeature([{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJNumericInputComponent), multi: true }]), i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 10, consts: [["numericInput", ""], ["type", "number", 1, "mj-input", "mj-numeric-input", 3, "input", "blur", "disabled", "value"]], template: function MJNumericInputComponent_Template(rf, ctx) { if (rf & 1) {
|
|
109
|
+
i0.ɵɵdomElementStart(0, "input", 1, 0);
|
|
90
110
|
i0.ɵɵdomListener("input", function MJNumericInputComponent_Template_input_input_0_listener($event) { return ctx.OnInput($event); })("blur", function MJNumericInputComponent_Template_input_blur_0_listener() { return ctx.OnBlur(); });
|
|
91
111
|
i0.ɵɵdomElementEnd();
|
|
92
112
|
} if (rf & 2) {
|
|
93
113
|
i0.ɵɵdomProperty("disabled", ctx.IsDisabled)("value", ctx.DisplayValue);
|
|
94
|
-
i0.ɵɵattribute("min", ctx.Min)("max", ctx.Max)("step", ctx.Step)("placeholder", ctx.Placeholder);
|
|
114
|
+
i0.ɵɵattribute("min", ctx.Min)("max", ctx.Max)("step", ctx.Step)("id", ctx.InputId || null)("aria-label", ctx.AriaLabel || null)("aria-labelledby", ctx.AriaLabelledBy || null)("aria-describedby", ctx.AriaDescribedBy || null)("placeholder", ctx.Placeholder);
|
|
95
115
|
} }, encapsulation: 2 });
|
|
96
116
|
}
|
|
97
117
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJNumericInputComponent, [{
|
|
@@ -100,8 +120,12 @@ export class MJNumericInputComponent {
|
|
|
100
120
|
selector: 'mj-numeric-input',
|
|
101
121
|
standalone: true,
|
|
102
122
|
template: `
|
|
103
|
-
<input type="number" class="mj-input mj-numeric-input"
|
|
123
|
+
<input #numericInput type="number" class="mj-input mj-numeric-input"
|
|
104
124
|
[attr.min]="Min" [attr.max]="Max" [attr.step]="Step"
|
|
125
|
+
[attr.id]="InputId || null"
|
|
126
|
+
[attr.aria-label]="AriaLabel || null"
|
|
127
|
+
[attr.aria-labelledby]="AriaLabelledBy || null"
|
|
128
|
+
[attr.aria-describedby]="AriaDescribedBy || null"
|
|
105
129
|
[attr.placeholder]="Placeholder" [disabled]="IsDisabled"
|
|
106
130
|
[value]="DisplayValue"
|
|
107
131
|
(input)="OnInput($event)" (blur)="OnBlur()" />
|
|
@@ -125,6 +149,9 @@ export class MJNumericInputComponent {
|
|
|
125
149
|
}], hostClass: [{
|
|
126
150
|
type: HostBinding,
|
|
127
151
|
args: ['class.mj-numeric-input-host']
|
|
152
|
+
}], numericInputEl: [{
|
|
153
|
+
type: ViewChild,
|
|
154
|
+
args: ['numericInput']
|
|
128
155
|
}] }); })();
|
|
129
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJNumericInputComponent, { className: "MJNumericInputComponent", filePath: "lib/numeric-input/numeric-input.component.ts", lineNumber:
|
|
156
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJNumericInputComponent, { className: "MJNumericInputComponent", filePath: "lib/numeric-input/numeric-input.component.ts", lineNumber: 45 }); })();
|
|
130
157
|
//# sourceMappingURL=numeric-input.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numeric-input.component.js","sourceRoot":"","sources":["../../../src/lib/numeric-input/numeric-input.component.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"numeric-input.component.js","sourceRoot":"","sources":["../../../src/lib/numeric-input/numeric-input.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AfterViewInit,\n ChangeDetectorRef,\n Component,\n ElementRef,\n HostBinding,\n Input,\n ViewChild,\n forwardRef,\n inject\n} from '@angular/core';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\nimport { MJNamedControlBase } from '../a11y/named-control.base';\nimport { WarnIfUnnamed } from '../a11y/unnamed-control-guard';\n\n/**\n * mj-numeric-input — Numeric input with min/max/step. Replaces `<kendo-numerictextbox>`.\n *\n * A spinbutton with no accessible name announces as \"spin button, blank\" (WCAG 2.1 4.1.2). Use\n * {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,\n * {@link MJNamedControlBase.AriaLabel} when none does. The control here is a real `<input>`, so\n * {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.\n *\n * @example\n * ```html\n * <mj-numeric-input AriaLabel=\"Quantity\" [(ngModel)]=\"quantity\" [Min]=\"0\" [Max]=\"100\" />\n * ```\n */\n@Component({\n selector: 'mj-numeric-input',\n standalone: true,\n template: `\n <input #numericInput type=\"number\" class=\"mj-input mj-numeric-input\"\n [attr.min]=\"Min\" [attr.max]=\"Max\" [attr.step]=\"Step\"\n [attr.id]=\"InputId || null\"\n [attr.aria-label]=\"AriaLabel || null\"\n [attr.aria-labelledby]=\"AriaLabelledBy || null\"\n [attr.aria-describedby]=\"AriaDescribedBy || null\"\n [attr.placeholder]=\"Placeholder\" [disabled]=\"IsDisabled\"\n [value]=\"DisplayValue\"\n (input)=\"OnInput($event)\" (blur)=\"OnBlur()\" />\n `,\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MJNumericInputComponent), multi: true }]\n})\nexport class MJNumericInputComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit {\n @Input() Min: number | null = null;\n @Input() Max: number | null = null;\n @Input() Step: number = 1;\n @Input() Format: string = '';\n @Input() Decimals: number | null = null;\n /**\n * Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`\n * (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is\n * routinely bound to an expression that changes over the control's lifetime, and the gate has\n * to follow it every time.\n */\n @Input()\n set Disabled(value: boolean) { this.disabledInput = value; this.syncDisabled(); }\n get Disabled(): boolean { return this.disabledInput; }\n @Input() Placeholder = '';\n @HostBinding('class.mj-numeric-input-host') readonly hostClass = true;\n @ViewChild('numericInput') private numericInputEl: ElementRef<HTMLInputElement> | undefined;\n\n /** The rendered `[disabled]` state — true when EITHER source says so. Assign via `syncDisabled()`. */\n IsDisabled = false;\n private disabledInput = false;\n private formDisabled = false;\n private cdr = inject(ChangeDetectorRef);\n\n /**\n * Recompute the gate from both of its sources. Called whenever either one changes.\n *\n * `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.\n * The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,\n * so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had\n * no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at\n * whatever the first compose produced and every later change to the input was dropped.\n */\n private syncDisabled(): void {\n const disabled = this.disabledInput || this.formDisabled;\n if (disabled === this.IsDisabled) return;\n this.IsDisabled = disabled;\n this.cdr.markForCheck();\n }\n\n DisplayValue: string | number = '';\n private internalValue: number | null = null;\n private onChange: (value: number | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n ngAfterViewInit(): void { WarnIfUnnamed(this.numericInputEl?.nativeElement, 'mj-numeric-input'); }\n\n OnInput(event: Event): void {\n const raw = (event.target as HTMLInputElement).value;\n if (raw === '' || raw === '-') { this.internalValue = null; this.onChange(null); return; }\n let num = parseFloat(raw);\n if (isNaN(num)) return;\n num = this.clamp(num);\n this.internalValue = num;\n this.onChange(num);\n }\n\n OnBlur(): void { this.onTouched(); this.formatDisplay(); }\n\n writeValue(value: number | null): void { this.internalValue = value; this.formatDisplay(); }\n registerOnChange(fn: (value: number | null) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.formDisabled = isDisabled; this.syncDisabled(); }\n\n private clamp(value: number): number {\n if (this.Min != null && value < this.Min) return this.Min;\n if (this.Max != null && value > this.Max) return this.Max;\n if (this.Decimals != null) { const f = Math.pow(10, this.Decimals); return Math.round(value * f) / f; }\n return value;\n }\n\n private formatDisplay(): void {\n if (this.internalValue == null) { this.DisplayValue = ''; return; }\n this.DisplayValue = this.Decimals != null ? this.internalValue.toFixed(this.Decimals) : this.internalValue;\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { EventEmitter } from '@angular/core';
|
|
1
|
+
import { AfterViewInit, EventEmitter } from '@angular/core';
|
|
2
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
2
3
|
import * as i0 from "@angular/core";
|
|
3
4
|
/**
|
|
4
5
|
* mj-page-search — Canonical in-page search input for dashboard headers and toolbars.
|
|
@@ -7,21 +8,49 @@ import * as i0 from "@angular/core";
|
|
|
7
8
|
* Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)
|
|
8
9
|
* — this one is a simple text input used for filtering page content.
|
|
9
10
|
*
|
|
11
|
+
* The `Placeholder` is the accessible name of last resort — it is what the name computation falls
|
|
12
|
+
* back to, and it disappears the moment the user types. Pass
|
|
13
|
+
* {@link MJNamedControlBase.AriaLabel} (or {@link MJNamedControlBase.AriaLabelledBy} when a visible
|
|
14
|
+
* label exists) so the box has a name that survives having text in it. The control is a real
|
|
15
|
+
* `<input>`, so {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
|
|
16
|
+
*
|
|
10
17
|
* Example:
|
|
11
18
|
* ```html
|
|
12
19
|
* <mj-page-search
|
|
20
|
+
* AriaLabel="Search templates"
|
|
13
21
|
* Placeholder="Search templates..."
|
|
14
22
|
* [Value]="searchTerm"
|
|
15
23
|
* (ValueChange)="onSearch($event)">
|
|
16
24
|
* </mj-page-search>
|
|
17
25
|
* ```
|
|
18
26
|
*/
|
|
19
|
-
export declare class MJPageSearchComponent {
|
|
27
|
+
export declare class MJPageSearchComponent extends MJNamedControlBase implements AfterViewInit {
|
|
28
|
+
/** The placeholder a caller gets by having said nothing — it names no particular search. */
|
|
29
|
+
static readonly GenericPlaceholder = "Search...";
|
|
20
30
|
Placeholder: string;
|
|
21
31
|
Value: string;
|
|
22
32
|
Icon: string;
|
|
23
33
|
ValueChange: EventEmitter<string>;
|
|
24
|
-
|
|
34
|
+
private searchInputEl;
|
|
35
|
+
Focused: boolean;
|
|
36
|
+
/** @deprecated Use {@link Focused}. */
|
|
37
|
+
get focused(): boolean;
|
|
38
|
+
/** @deprecated Use {@link Focused}. */
|
|
39
|
+
set focused(value: boolean);
|
|
40
|
+
/**
|
|
41
|
+
* `PlaceholderIsName` is passed here and nowhere else: this is a toolbar widget whose placeholder
|
|
42
|
+
* ("Search templates…") IS the caller's statement of what the box searches. On a form control a
|
|
43
|
+
* placeholder is not a name — it disappears as soon as the user types — so those controls warn
|
|
44
|
+
* without one.
|
|
45
|
+
*
|
|
46
|
+
* It is not passed unconditionally, or the guard could never fire here at all: the default
|
|
47
|
+
* placeholder is non-empty, so accepting any placeholder would accept `'Search...'`, which tells a
|
|
48
|
+
* screen-reader user nothing about what is being searched. Only a placeholder the caller actually
|
|
49
|
+
* chose counts.
|
|
50
|
+
*/
|
|
51
|
+
ngAfterViewInit(): void;
|
|
52
|
+
OnInput(event: Event): void;
|
|
53
|
+
/** @deprecated Use {@link OnInput}. */
|
|
25
54
|
onInput(event: Event): void;
|
|
26
55
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJPageSearchComponent, never>;
|
|
27
56
|
static ɵcmp: i0.ɵɵComponentDeclaration<MJPageSearchComponent, "mj-page-search", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "Value": { "alias": "Value"; "required": false; }; "Icon": { "alias": "Icon"; "required": false; }; }, { "ValueChange": "ValueChange"; }, never, never, true, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-search.component.d.ts","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"page-search.component.d.ts","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAGb,YAAY,EAIb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAGhE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAgFa,qBAAsB,SAAQ,kBAAmB,YAAW,aAAa;IACpF,4FAA4F;IAC5F,MAAM,CAAC,QAAQ,CAAC,kBAAkB,eAAe;IAExC,WAAW,EAAE,MAAM,CAA4C;IAC/D,KAAK,EAAE,MAAM,CAAM;IACnB,IAAI,EAAE,MAAM,CAAwB;IACnC,WAAW,uBAA8B;IAEzB,OAAO,CAAC,aAAa,CAA2C;IAEnF,OAAO,EAAE,OAAO,CAAS;IAEhC,uCAAuC;IACvC,IAAW,OAAO,IAAI,OAAO,CAE5B;IACD,uCAAuC;IACvC,IAAW,OAAO,CAAC,KAAK,EAAE,OAAO,EAEhC;IAED;;;;;;;;;;OAUG;IACI,eAAe,IAAI,IAAI;IAMvB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMlC,uCAAuC;IAChC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;yCA9CvB,qBAAqB;2CAArB,qBAAqB;CAiDjC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
1
|
+
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
|
2
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
3
|
+
import { WarnIfUnnamed } from '../a11y/unnamed-control-guard';
|
|
2
4
|
import * as i0 from "@angular/core";
|
|
5
|
+
const _c0 = ["searchInput"];
|
|
3
6
|
/**
|
|
4
7
|
* mj-page-search — Canonical in-page search input for dashboard headers and toolbars.
|
|
5
8
|
* Replaces per-page `.search-input-wrapper` rules so styling can't drift.
|
|
@@ -7,31 +10,74 @@ import * as i0 from "@angular/core";
|
|
|
7
10
|
* Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)
|
|
8
11
|
* — this one is a simple text input used for filtering page content.
|
|
9
12
|
*
|
|
13
|
+
* The `Placeholder` is the accessible name of last resort — it is what the name computation falls
|
|
14
|
+
* back to, and it disappears the moment the user types. Pass
|
|
15
|
+
* {@link MJNamedControlBase.AriaLabel} (or {@link MJNamedControlBase.AriaLabelledBy} when a visible
|
|
16
|
+
* label exists) so the box has a name that survives having text in it. The control is a real
|
|
17
|
+
* `<input>`, so {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.
|
|
18
|
+
*
|
|
10
19
|
* Example:
|
|
11
20
|
* ```html
|
|
12
21
|
* <mj-page-search
|
|
22
|
+
* AriaLabel="Search templates"
|
|
13
23
|
* Placeholder="Search templates..."
|
|
14
24
|
* [Value]="searchTerm"
|
|
15
25
|
* (ValueChange)="onSearch($event)">
|
|
16
26
|
* </mj-page-search>
|
|
17
27
|
* ```
|
|
18
28
|
*/
|
|
19
|
-
export class MJPageSearchComponent {
|
|
20
|
-
|
|
29
|
+
export class MJPageSearchComponent extends MJNamedControlBase {
|
|
30
|
+
/** The placeholder a caller gets by having said nothing — it names no particular search. */
|
|
31
|
+
static GenericPlaceholder = 'Search...';
|
|
32
|
+
Placeholder = MJPageSearchComponent.GenericPlaceholder;
|
|
21
33
|
Value = '';
|
|
22
34
|
Icon = 'fa-solid fa-search';
|
|
23
35
|
ValueChange = new EventEmitter();
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
searchInputEl;
|
|
37
|
+
Focused = false;
|
|
38
|
+
/** @deprecated Use {@link Focused}. */
|
|
39
|
+
get focused() {
|
|
40
|
+
return this.Focused;
|
|
41
|
+
}
|
|
42
|
+
/** @deprecated Use {@link Focused}. */
|
|
43
|
+
set focused(value) {
|
|
44
|
+
this.Focused = value;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `PlaceholderIsName` is passed here and nowhere else: this is a toolbar widget whose placeholder
|
|
48
|
+
* ("Search templates…") IS the caller's statement of what the box searches. On a form control a
|
|
49
|
+
* placeholder is not a name — it disappears as soon as the user types — so those controls warn
|
|
50
|
+
* without one.
|
|
51
|
+
*
|
|
52
|
+
* It is not passed unconditionally, or the guard could never fire here at all: the default
|
|
53
|
+
* placeholder is non-empty, so accepting any placeholder would accept `'Search...'`, which tells a
|
|
54
|
+
* screen-reader user nothing about what is being searched. Only a placeholder the caller actually
|
|
55
|
+
* chose counts.
|
|
56
|
+
*/
|
|
57
|
+
ngAfterViewInit() {
|
|
58
|
+
WarnIfUnnamed(this.searchInputEl?.nativeElement, 'mj-page-search', {
|
|
59
|
+
PlaceholderIsName: this.Placeholder !== MJPageSearchComponent.GenericPlaceholder
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
OnInput(event) {
|
|
26
63
|
const v = event.target.value;
|
|
27
64
|
this.Value = v;
|
|
28
65
|
this.ValueChange.emit(v);
|
|
29
66
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
/** @deprecated Use {@link OnInput}. */
|
|
68
|
+
onInput(event) {
|
|
69
|
+
return this.OnInput(event);
|
|
70
|
+
}
|
|
71
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵMJPageSearchComponent_BaseFactory; return function MJPageSearchComponent_Factory(__ngFactoryType__) { return (ɵMJPageSearchComponent_BaseFactory || (ɵMJPageSearchComponent_BaseFactory = i0.ɵɵgetInheritedFactory(MJPageSearchComponent)))(__ngFactoryType__ || MJPageSearchComponent); }; })();
|
|
72
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJPageSearchComponent, selectors: [["mj-page-search"]], viewQuery: function MJPageSearchComponent_Query(rf, ctx) { if (rf & 1) {
|
|
73
|
+
i0.ɵɵviewQuery(_c0, 5);
|
|
74
|
+
} if (rf & 2) {
|
|
75
|
+
let _t;
|
|
76
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchInputEl = _t.first);
|
|
77
|
+
} }, inputs: { Placeholder: "Placeholder", Value: "Value", Icon: "Icon" }, outputs: { ValueChange: "ValueChange" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 10, consts: [["searchInput", ""], [1, "mj-page-search"], ["aria-hidden", "true"], ["type", "text", 3, "input", "focus", "blur", "placeholder", "value"]], template: function MJPageSearchComponent_Template(rf, ctx) { if (rf & 1) {
|
|
78
|
+
i0.ɵɵdomElementStart(0, "div", 1);
|
|
79
|
+
i0.ɵɵdomElement(1, "i", 2);
|
|
80
|
+
i0.ɵɵdomElementStart(2, "input", 3, 0);
|
|
35
81
|
i0.ɵɵdomListener("input", function MJPageSearchComponent_Template_input_input_2_listener($event) { return ctx.onInput($event); })("focus", function MJPageSearchComponent_Template_input_focus_2_listener() { return ctx.focused = true; })("blur", function MJPageSearchComponent_Template_input_blur_2_listener() { return ctx.focused = false; });
|
|
36
82
|
i0.ɵɵdomElementEnd()();
|
|
37
83
|
} if (rf & 2) {
|
|
@@ -40,15 +86,22 @@ export class MJPageSearchComponent {
|
|
|
40
86
|
i0.ɵɵclassMap(ctx.Icon);
|
|
41
87
|
i0.ɵɵadvance();
|
|
42
88
|
i0.ɵɵdomProperty("placeholder", ctx.Placeholder)("value", ctx.Value);
|
|
89
|
+
i0.ɵɵattribute("id", ctx.InputId || null)("aria-label", ctx.AriaLabel || null)("aria-labelledby", ctx.AriaLabelledBy || null)("aria-describedby", ctx.AriaDescribedBy || null);
|
|
43
90
|
} }, styles: ["[_nghost-%COMP%] {\n display: inline-flex;\n min-width: 220px;\n }\n\n \n\n\n\n\n .mj-page-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-1) var(--mj-space-3);\n font-family: var(--mj-font-family);\n font-size: var(--mj-text-sm);\n line-height: 1.5;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors), box-shadow var(--mj-transition-base);\n min-height: 32px;\n box-sizing: border-box;\n }\n\n .mj-page-search[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n }\n\n .mj-page-search--focused[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n }\n\n .mj-page-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .mj-page-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n color: var(--mj-text-primary);\n min-width: 0;\n }\n\n .mj-page-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n }"] });
|
|
44
91
|
}
|
|
45
92
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJPageSearchComponent, [{
|
|
46
93
|
type: Component,
|
|
47
94
|
args: [{ selector: 'mj-page-search', standalone: true, template: `
|
|
48
95
|
<div class="mj-page-search" [class.mj-page-search--focused]="focused">
|
|
49
|
-
|
|
96
|
+
<!-- Decorative: the magnifier repeats what the name and placeholder already say. -->
|
|
97
|
+
<i [class]="Icon" aria-hidden="true"></i>
|
|
50
98
|
<input
|
|
99
|
+
#searchInput
|
|
51
100
|
type="text"
|
|
101
|
+
[attr.id]="InputId || null"
|
|
102
|
+
[attr.aria-label]="AriaLabel || null"
|
|
103
|
+
[attr.aria-labelledby]="AriaLabelledBy || null"
|
|
104
|
+
[attr.aria-describedby]="AriaDescribedBy || null"
|
|
52
105
|
[placeholder]="Placeholder"
|
|
53
106
|
[value]="Value"
|
|
54
107
|
(input)="onInput($event)"
|
|
@@ -64,6 +117,9 @@ export class MJPageSearchComponent {
|
|
|
64
117
|
type: Input
|
|
65
118
|
}], ValueChange: [{
|
|
66
119
|
type: Output
|
|
120
|
+
}], searchInputEl: [{
|
|
121
|
+
type: ViewChild,
|
|
122
|
+
args: ['searchInput']
|
|
67
123
|
}] }); })();
|
|
68
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJPageSearchComponent, { className: "MJPageSearchComponent", filePath: "lib/page-search/page-search.component.ts", lineNumber:
|
|
124
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJPageSearchComponent, { className: "MJPageSearchComponent", filePath: "lib/page-search/page-search.component.ts", lineNumber: 116 }); })();
|
|
69
125
|
//# sourceMappingURL=page-search.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-search.component.js","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"page-search.component.js","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAET,YAAY,EACZ,KAAK,EACL,MAAM,EACN,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;;;AAE9D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAiFH,MAAM,OAAO,qBAAsB,SAAQ,kBAAkB;IAC3D,4FAA4F;IAC5F,MAAM,CAAU,kBAAkB,GAAG,WAAW,CAAC;IAExC,WAAW,GAAW,qBAAqB,CAAC,kBAAkB,CAAC;IAC/D,KAAK,GAAW,EAAE,CAAC;IACnB,IAAI,GAAW,oBAAoB,CAAC;IACnC,WAAW,GAAG,IAAI,YAAY,EAAU,CAAC;IAEjB,aAAa,CAA2C;IAEnF,OAAO,GAAY,KAAK,CAAC;IAEhC,uCAAuC;IACvC,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,uCAAuC;IACvC,IAAW,OAAO,CAAC,KAAc;QAC/B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;;;;;;;;OAUG;IACI,eAAe;QACpB,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE;YACjE,iBAAiB,EAAE,IAAI,CAAC,WAAW,KAAK,qBAAqB,CAAC,kBAAkB;SACjF,CAAC,CAAC;IACL,CAAC;IAEM,OAAO,CAAC,KAAY;QACzB,MAAM,CAAC,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,uCAAuC;IAChC,OAAO,CAAC,KAAY;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;iQAhDU,qBAAqB,yBAArB,qBAAqB;6DAArB,qBAAqB;;;;;;YA5E9B,iCAAsE;YAEpE,0BAAyC;YACzC,sCAW6B;YAA3B,AADA,AADA,0GAAS,mBAAe,IAAC,kGACN,IAAI,IAAC,gGACN,KAAK,IAAC;YAC5B,AAZE,oBAW6B,EACzB;;YAfsB,sDAAyC;YAEhE,cAAc;YAAd,uBAAc;YAQf,cAA2B;YAC3B,AADA,gDAA2B,oBACZ;;;;iFAiEV,qBAAqB;cAhFjC,SAAS;2BACE,gBAAgB,cACd,IAAI,YACN;;;;;;;;;;;;;;;;;GAiBT;;kBAgEA,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kBAEN,SAAS;mBAAC,aAAa;;kFATb,qBAAqB","sourcesContent":["import {\n AfterViewInit,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n Output,\n ViewChild\n} from '@angular/core';\nimport { MJNamedControlBase } from '../a11y/named-control.base';\nimport { WarnIfUnnamed } from '../a11y/unnamed-control-guard';\n\n/**\n * mj-page-search — Canonical in-page search input for dashboard headers and toolbars.\n * Replaces per-page `.search-input-wrapper` rules so styling can't drift.\n *\n * Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)\n * — this one is a simple text input used for filtering page content.\n *\n * The `Placeholder` is the accessible name of last resort — it is what the name computation falls\n * back to, and it disappears the moment the user types. Pass\n * {@link MJNamedControlBase.AriaLabel} (or {@link MJNamedControlBase.AriaLabelledBy} when a visible\n * label exists) so the box has a name that survives having text in it. The control is a real\n * `<input>`, so {@link MJNamedControlBase.InputId} IS a valid `<label for>` target.\n *\n * Example:\n * ```html\n * <mj-page-search\n * AriaLabel=\"Search templates\"\n * Placeholder=\"Search templates...\"\n * [Value]=\"searchTerm\"\n * (ValueChange)=\"onSearch($event)\">\n * </mj-page-search>\n * ```\n */\n@Component({\n selector: 'mj-page-search',\n standalone: true,\n template: `\n <div class=\"mj-page-search\" [class.mj-page-search--focused]=\"focused\">\n <!-- Decorative: the magnifier repeats what the name and placeholder already say. -->\n <i [class]=\"Icon\" aria-hidden=\"true\"></i>\n <input\n #searchInput\n type=\"text\"\n [attr.id]=\"InputId || null\"\n [attr.aria-label]=\"AriaLabel || null\"\n [attr.aria-labelledby]=\"AriaLabelledBy || null\"\n [attr.aria-describedby]=\"AriaDescribedBy || null\"\n [placeholder]=\"Placeholder\"\n [value]=\"Value\"\n (input)=\"onInput($event)\"\n (focus)=\"focused = true\"\n (blur)=\"focused = false\" />\n </div>\n `,\n styles: [`\n :host {\n display: inline-flex;\n min-width: 220px;\n }\n\n /* Compact toolbar density (32px) to match mjButton size=\"sm\" and other\n header widgets. White background + border-default for visual differentiation\n on both the page-header (white) and body (sunken) surfaces.\n Note: this is intentionally tighter than .mj-input (38px) because\n mj-page-search is a toolbar widget, not a form field. */\n .mj-page-search {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-1) var(--mj-space-3);\n font-family: var(--mj-font-family);\n font-size: var(--mj-text-sm);\n line-height: 1.5;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors), box-shadow var(--mj-transition-base);\n min-height: 32px;\n box-sizing: border-box;\n }\n\n .mj-page-search:hover {\n border-color: var(--mj-border-strong);\n }\n\n .mj-page-search--focused {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n }\n\n .mj-page-search i {\n color: var(--mj-text-muted);\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .mj-page-search input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n color: var(--mj-text-primary);\n min-width: 0;\n }\n\n .mj-page-search input::placeholder {\n color: var(--mj-text-disabled);\n }\n `]\n})\nexport class MJPageSearchComponent extends MJNamedControlBase implements AfterViewInit {\n /** The placeholder a caller gets by having said nothing — it names no particular search. */\n static readonly GenericPlaceholder = 'Search...';\n\n @Input() Placeholder: string = MJPageSearchComponent.GenericPlaceholder;\n @Input() Value: string = '';\n @Input() Icon: string = 'fa-solid fa-search';\n @Output() ValueChange = new EventEmitter<string>();\n\n @ViewChild('searchInput') private searchInputEl: ElementRef<HTMLInputElement> | undefined;\n\n public Focused: boolean = false;\n\n /** @deprecated Use {@link Focused}. */\n public get focused(): boolean {\n return this.Focused;\n }\n /** @deprecated Use {@link Focused}. */\n public set focused(value: boolean) {\n this.Focused = value;\n }\n\n /**\n * `PlaceholderIsName` is passed here and nowhere else: this is a toolbar widget whose placeholder\n * (\"Search templates…\") IS the caller's statement of what the box searches. On a form control a\n * placeholder is not a name — it disappears as soon as the user types — so those controls warn\n * without one.\n *\n * It is not passed unconditionally, or the guard could never fire here at all: the default\n * placeholder is non-empty, so accepting any placeholder would accept `'Search...'`, which tells a\n * screen-reader user nothing about what is being searched. Only a placeholder the caller actually\n * chose counts.\n */\n public ngAfterViewInit(): void {\n WarnIfUnnamed(this.searchInputEl?.nativeElement, 'mj-page-search', {\n PlaceholderIsName: this.Placeholder !== MJPageSearchComponent.GenericPlaceholder\n });\n }\n\n public OnInput(event: Event): void {\n const v = (event.target as HTMLInputElement).value;\n this.Value = v;\n this.ValueChange.emit(v);\n }\n\n /** @deprecated Use {@link OnInput}. */\n public onInput(event: Event): void {\n return this.OnInput(event);\n }\n}\n"]}
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
import { AfterViewInit } from '@angular/core';
|
|
1
2
|
import { ControlValueAccessor } from '@angular/forms';
|
|
3
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
2
4
|
import * as i0 from "@angular/core";
|
|
3
5
|
/**
|
|
4
6
|
* mj-switch — Toggle switch. Replaces `<kendo-switch>`.
|
|
7
|
+
*
|
|
8
|
+
* Every switch needs an ACCESSIBLE NAME. Without one it announces as "switch, on" — or, worse, as
|
|
9
|
+
* its own STATE, because `OnLabel`/`OffLabel` render inside the button and a `role=switch` takes
|
|
10
|
+
* its name from its contents when nothing else names it: a toggle labelled "On" that announces
|
|
11
|
+
* "On, switch, on" says nothing about what it toggles (WCAG 2.1 4.1.2). Use
|
|
12
|
+
* {@link MJNamedControlBase.AriaLabelledBy} when a visible label exists,
|
|
13
|
+
* {@link MJNamedControlBase.AriaLabel} when none does; either one overrides that state text.
|
|
14
|
+
*
|
|
15
|
+
* The switch is a `<button>`, which IS a labelable element, so
|
|
16
|
+
* {@link MJNamedControlBase.InputId} doubles as a `<label for>` target: the label names the switch
|
|
17
|
+
* — overriding the On/Off text, since an associated label outranks an element's own contents — and
|
|
18
|
+
* clicking it focuses and toggles the switch, which `AriaLabelledBy` alone does not give you.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```html
|
|
22
|
+
* <mj-switch AriaLabel="Email notifications" [(ngModel)]="isEnabled" OnLabel="On" OffLabel="Off" />
|
|
23
|
+
* ```
|
|
5
24
|
*/
|
|
6
|
-
export declare class MJSwitchComponent implements ControlValueAccessor {
|
|
25
|
+
export declare class MJSwitchComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit {
|
|
7
26
|
OnLabel: string;
|
|
8
27
|
OffLabel: string;
|
|
9
28
|
/**
|
|
@@ -15,6 +34,7 @@ export declare class MJSwitchComponent implements ControlValueAccessor {
|
|
|
15
34
|
set Disabled(value: boolean);
|
|
16
35
|
get Disabled(): boolean;
|
|
17
36
|
readonly hostClass = true;
|
|
37
|
+
private switchButtonEl;
|
|
18
38
|
Value: boolean;
|
|
19
39
|
/** The gate on `Toggle()` — true when EITHER source says so. Assign only via `syncDisabled()`. */
|
|
20
40
|
IsDisabled: boolean;
|
|
@@ -33,6 +53,7 @@ export declare class MJSwitchComponent implements ControlValueAccessor {
|
|
|
33
53
|
* whatever the first compose produced and every later change to the input was dropped.
|
|
34
54
|
*/
|
|
35
55
|
private syncDisabled;
|
|
56
|
+
ngAfterViewInit(): void;
|
|
36
57
|
Toggle(): void;
|
|
37
58
|
OnTouched(): void;
|
|
38
59
|
writeValue(value: boolean): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"switch.component.d.ts","sourceRoot":"","sources":["../../../src/lib/switch/switch.component.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"switch.component.d.ts","sourceRoot":"","sources":["../../../src/lib/switch/switch.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EASd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAqB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;;AAGhE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAoBa,iBAAkB,SAAQ,kBAAmB,YAAW,oBAAoB,EAAE,aAAa;IAC7F,OAAO,SAAM;IACb,QAAQ,SAAM;IACvB;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAsD;IACjF,IAAI,QAAQ,IAAI,OAAO,CAA+B;IACjB,QAAQ,CAAC,SAAS,QAAQ;IACpC,OAAO,CAAC,cAAc,CAA4C;IAE7F,KAAK,UAAS;IACd,kGAAkG;IAClG,UAAU,UAAS;IACnB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,SAAS,CAAwB;IAEzC;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IAOpB,eAAe,IAAI,IAAI;IAEvB,MAAM,IAAI,IAAI;IACd,SAAS,IAAI,IAAI;IACjB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAChC,gBAAgB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IACpD,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI;IACvC,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;yCA/ChC,iBAAiB;2CAAjB,iBAAiB;CAgD7B"}
|