@ekzo-dev/bootstrap-addons 5.3.19 → 5.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/forms/duration-input/duration-input.html +2 -8
- package/src/forms/duration-input/duration-input.stories.ts +39 -39
- package/src/forms/duration-input/duration-input.ts +12 -6
- package/src/forms/json-input/json-input.stories.ts +59 -59
- package/src/forms/json-input/json-input.ts +9 -9
- package/src/forms/select-dropdown/index.ts +1 -0
- package/src/forms/{select/select.scss → select-dropdown/select-dropdown.scss} +8 -5
- package/src/forms/{select/select.ts → select-dropdown/select-dropdown.ts} +19 -19
- package/src/forms/select-dropdown/select.stories.ts +89 -0
- package/src/index.ts +1 -1
- package/src/forms/select/index.ts +0 -1
- package/src/forms/select/select.stories.ts +0 -89
- /package/src/forms/{select → select-dropdown}/filter.ts +0 -0
- /package/src/forms/{select/select.html → select-dropdown/select-dropdown.html} +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekzo-dev/bootstrap-addons",
|
|
3
3
|
"description": "Aurelia Bootstrap additional component",
|
|
4
|
-
"version": "5.3.
|
|
4
|
+
"version": "5.3.21",
|
|
5
5
|
"homepage": "https://github.com/ekzo-dev/aurelia-components/tree/main/packages/bootstrap-addons",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@ekzo-dev/bootstrap": "~5.3.
|
|
12
|
+
"@ekzo-dev/bootstrap": "~5.3.6",
|
|
13
13
|
"@ekzo-dev/vanilla-jsoneditor": "~3.11.0",
|
|
14
|
-
"@ekzo-dev/toolkit": "^1.
|
|
14
|
+
"@ekzo-dev/toolkit": "^1.3.0",
|
|
15
15
|
"@fortawesome/free-solid-svg-icons": "^7.0.1",
|
|
16
16
|
"@types/json-schema": "^7.0.14",
|
|
17
17
|
"@js-temporal/polyfill": "^0.5.1",
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
<template class="${floatingLabel ? 'form-floating' : ''}">
|
|
2
2
|
<label for.one-time="id" if.bind="label && !floatingLabel" class="form-label">${label}</label>
|
|
3
3
|
<fieldset class="${classes}" disabled.bind="disabled">
|
|
4
|
-
<input
|
|
5
|
-
|
|
6
|
-
id.one-time="id"
|
|
7
|
-
required.bind="required"
|
|
8
|
-
value.bind="value"
|
|
9
|
-
form.bind="form & attr"
|
|
10
|
-
focus.trigger="focus()"
|
|
11
|
-
/>
|
|
4
|
+
<input type="text" id.one-time="id" value.bind="value" focus.trigger="focus()" ref="control" />
|
|
5
|
+
|
|
12
6
|
<input type="number" min="0" value.bind="duration.years" placeholder="--" />
|
|
13
7
|
<span>${labels.years}</span>
|
|
14
8
|
<input type="number" min="0" value.bind="duration.months" placeholder="--" />
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { BsButton } from '@ekzo-dev/bootstrap';
|
|
2
|
-
import { createComponentTemplate, Meta, Story, StoryFnAureliaReturnType } from '@storybook/aurelia';
|
|
3
|
-
|
|
4
|
-
import { selectControl } from '../../../../../.storybook/helpers';
|
|
5
|
-
|
|
6
|
-
import { BsDurationInput } from '.';
|
|
7
|
-
|
|
8
|
-
const meta: Meta = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export default meta;
|
|
21
|
-
|
|
22
|
-
const Overview: Story = (args): StoryFnAureliaReturnType => ({
|
|
23
|
-
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const Validation: Story = (args): StoryFnAureliaReturnType => ({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
Validation.args = {
|
|
35
|
-
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// eslint-disable-next-line
|
|
39
|
-
export { Overview, Validation };
|
|
1
|
+
// import { BsButton } from '@ekzo-dev/bootstrap';
|
|
2
|
+
// import { createComponentTemplate, Meta, Story, StoryFnAureliaReturnType } from '@storybook/aurelia';
|
|
3
|
+
//
|
|
4
|
+
// import { selectControl } from '../../../../../.storybook/helpers';
|
|
5
|
+
//
|
|
6
|
+
// import { BsDurationInput } from '.';
|
|
7
|
+
//
|
|
8
|
+
// const meta: Meta = {
|
|
9
|
+
// title: 'Ekzo / Bootstrap Addons / Forms / Duration input',
|
|
10
|
+
// component: BsDurationInput,
|
|
11
|
+
// args: {
|
|
12
|
+
// value: 'P5DT1Hasds',
|
|
13
|
+
// label: 'Duration',
|
|
14
|
+
// },
|
|
15
|
+
// argTypes: {
|
|
16
|
+
// bsSize: selectControl(['', 'sm', 'lg']),
|
|
17
|
+
// },
|
|
18
|
+
// };
|
|
19
|
+
//
|
|
20
|
+
// export default meta;
|
|
21
|
+
//
|
|
22
|
+
// const Overview: Story = (args): StoryFnAureliaReturnType => ({
|
|
23
|
+
// props: args,
|
|
24
|
+
// });
|
|
25
|
+
//
|
|
26
|
+
// const Validation: Story = (args): StoryFnAureliaReturnType => ({
|
|
27
|
+
// props: args,
|
|
28
|
+
// template: `<form class='was-validated'>${createComponentTemplate(
|
|
29
|
+
// BsDurationInput
|
|
30
|
+
// )}<br>\${value} <button bs-button>Validate</button></form>`,
|
|
31
|
+
// components: [BsButton],
|
|
32
|
+
// });
|
|
33
|
+
//
|
|
34
|
+
// Validation.args = {
|
|
35
|
+
// required: true,
|
|
36
|
+
// };
|
|
37
|
+
//
|
|
38
|
+
// // eslint-disable-next-line
|
|
39
|
+
// export { Overview, Validation };
|
|
@@ -7,12 +7,17 @@ import { coerceBoolean } from '@ekzo-dev/toolkit';
|
|
|
7
7
|
import { Temporal } from '@js-temporal/polyfill';
|
|
8
8
|
import { bindable, BindingMode, customElement } from 'aurelia';
|
|
9
9
|
|
|
10
|
-
type
|
|
10
|
+
type Writable<T> = {
|
|
11
|
+
-readonly [P in keyof T]: T[P];
|
|
12
|
+
};
|
|
13
|
+
type Duration = Writable<
|
|
14
|
+
Partial<Pick<Temporal.Duration, 'years' | 'months' | 'days' | 'hours' | 'minutes' | 'seconds'>>
|
|
15
|
+
>;
|
|
11
16
|
type DurationLabels = {
|
|
12
17
|
[K in keyof Duration]: string;
|
|
13
18
|
};
|
|
14
19
|
|
|
15
|
-
const durationKeys = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'] as const;
|
|
20
|
+
const durationKeys: (keyof Duration)[] = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'] as const;
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
23
|
* https://github.com/whatwg/html/issues/5488
|
|
@@ -45,7 +50,7 @@ export class BsDurationInput extends BaseField implements EventListenerObject {
|
|
|
45
50
|
bsSize?: Size;
|
|
46
51
|
|
|
47
52
|
@bindable(coerceBoolean)
|
|
48
|
-
floatingLabel: boolean =
|
|
53
|
+
floatingLabel: boolean = this.config.floatingLabels;
|
|
49
54
|
|
|
50
55
|
duration: Duration = {};
|
|
51
56
|
|
|
@@ -81,7 +86,7 @@ export class BsDurationInput extends BaseField implements EventListenerObject {
|
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
handleEvent(event: KeyboardEvent | ClipboardEvent): void {
|
|
84
|
-
const data = event instanceof KeyboardEvent ? event.key : event.clipboardData
|
|
89
|
+
const data = event instanceof KeyboardEvent ? event.key : event.clipboardData!.getData('text');
|
|
85
90
|
|
|
86
91
|
// don't allow non-numeric values
|
|
87
92
|
if (!/^\d+$/.test(data)) {
|
|
@@ -101,10 +106,10 @@ export class BsDurationInput extends BaseField implements EventListenerObject {
|
|
|
101
106
|
private _parseDuration(value: string) {
|
|
102
107
|
try {
|
|
103
108
|
const duration = Temporal.Duration.from(value);
|
|
104
|
-
const result = {};
|
|
109
|
+
const result: Duration = {};
|
|
105
110
|
|
|
106
111
|
durationKeys.forEach((key) => {
|
|
107
|
-
result[key] = duration[key] ? duration[key]
|
|
112
|
+
result[key] = duration[key] ? duration[key] : undefined;
|
|
108
113
|
});
|
|
109
114
|
this.duration = result;
|
|
110
115
|
} catch (error) {
|
|
@@ -118,6 +123,7 @@ export class BsDurationInput extends BaseField implements EventListenerObject {
|
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
#getLabels(): DurationLabels {
|
|
126
|
+
// @ts-ignore
|
|
121
127
|
const str: string = new Intl['DurationFormat'](navigator.language, { style: 'narrow' }).format({
|
|
122
128
|
years: 1,
|
|
123
129
|
months: 1,
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import { Meta, Story, StoryFnAureliaReturnType } from '@storybook/aurelia';
|
|
2
|
-
|
|
3
|
-
import { BsJsonInput } from '.';
|
|
4
|
-
|
|
5
|
-
const meta: Meta = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default meta;
|
|
11
|
-
|
|
12
|
-
const Overview: Story = (args): StoryFnAureliaReturnType => ({
|
|
13
|
-
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
Overview.args = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const JsonSchemaEditor: Story = (args): StoryFnAureliaReturnType => ({
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
JsonSchemaEditor.args = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// eslint-disable-next-line
|
|
59
|
-
export { Overview, JsonSchemaEditor };
|
|
1
|
+
// import { Meta, Story, StoryFnAureliaReturnType } from '@storybook/aurelia';
|
|
2
|
+
//
|
|
3
|
+
// import { BsJsonInput } from '.';
|
|
4
|
+
//
|
|
5
|
+
// const meta: Meta = {
|
|
6
|
+
// title: 'Ekzo / Bootstrap Addons / Forms / Json input',
|
|
7
|
+
// component: BsJsonInput,
|
|
8
|
+
// };
|
|
9
|
+
//
|
|
10
|
+
// export default meta;
|
|
11
|
+
//
|
|
12
|
+
// const Overview: Story = (args): StoryFnAureliaReturnType => ({
|
|
13
|
+
// props: args,
|
|
14
|
+
// });
|
|
15
|
+
//
|
|
16
|
+
// Overview.args = {
|
|
17
|
+
// jsonSchema: {
|
|
18
|
+
// $schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
19
|
+
// type: 'object',
|
|
20
|
+
// properties: {
|
|
21
|
+
// enum: {
|
|
22
|
+
// type: 'string',
|
|
23
|
+
// enum: ['1', '2', '3'],
|
|
24
|
+
// },
|
|
25
|
+
// boolean: {
|
|
26
|
+
// type: 'boolean',
|
|
27
|
+
// },
|
|
28
|
+
// email: {
|
|
29
|
+
// type: 'string',
|
|
30
|
+
// format: 'email',
|
|
31
|
+
// },
|
|
32
|
+
// number: {
|
|
33
|
+
// type: 'number',
|
|
34
|
+
// multipleOf: 0.0001,
|
|
35
|
+
// },
|
|
36
|
+
// },
|
|
37
|
+
// required: ['enum'],
|
|
38
|
+
// },
|
|
39
|
+
// value: {
|
|
40
|
+
// number: 1.11,
|
|
41
|
+
// enum: '1',
|
|
42
|
+
// },
|
|
43
|
+
// };
|
|
44
|
+
//
|
|
45
|
+
// const JsonSchemaEditor: Story = (args): StoryFnAureliaReturnType => ({
|
|
46
|
+
// props: args,
|
|
47
|
+
// });
|
|
48
|
+
//
|
|
49
|
+
// JsonSchemaEditor.args = {
|
|
50
|
+
// jsonSchema: true,
|
|
51
|
+
// value: {
|
|
52
|
+
// $schema: 'http://json-schema.org/draft-07/schema#',
|
|
53
|
+
// type: 'object',
|
|
54
|
+
// properties: {},
|
|
55
|
+
// },
|
|
56
|
+
// };
|
|
57
|
+
//
|
|
58
|
+
// // eslint-disable-next-line
|
|
59
|
+
// export { Overview, JsonSchemaEditor };
|
|
@@ -21,7 +21,7 @@ import { ProxyObservable } from '@aurelia/runtime';
|
|
|
21
21
|
import { coerceBoolean } from '@ekzo-dev/toolkit';
|
|
22
22
|
import { JsonEditor } from '@ekzo-dev/vanilla-jsoneditor';
|
|
23
23
|
import { faUpRightAndDownLeftFromCenter } from '@fortawesome/free-solid-svg-icons/faUpRightAndDownLeftFromCenter';
|
|
24
|
-
import Ajv, { ErrorObject, Options } from 'ajv';
|
|
24
|
+
import Ajv, { type AnySchema, type ErrorObject, type Options } from 'ajv';
|
|
25
25
|
import Ajv2019 from 'ajv/dist/2019';
|
|
26
26
|
import Ajv2020 from 'ajv/dist/2020';
|
|
27
27
|
import addFormats from 'ajv-formats';
|
|
@@ -49,7 +49,7 @@ export class BsJsonInput {
|
|
|
49
49
|
@bindable(coerceBoolean)
|
|
50
50
|
disabled: boolean = false;
|
|
51
51
|
|
|
52
|
-
@bindable({ set: (v:
|
|
52
|
+
@bindable({ set: (v: unknown) => (v === '' || v === true || v === 'true' ? true : v) })
|
|
53
53
|
jsonSchema?: JSONSchema | SchemaNode | boolean;
|
|
54
54
|
|
|
55
55
|
@bindable()
|
|
@@ -77,7 +77,7 @@ export class BsJsonInput {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
onRenderValue = (props: RenderValueProps): RenderValueComponentDescription[] => {
|
|
80
|
-
let result: RenderValueComponentDescription[] | null;
|
|
80
|
+
// let result: RenderValueComponentDescription[] | null;
|
|
81
81
|
// const { jsonSchema } = this;
|
|
82
82
|
const { editorModule } = this.editorComponent;
|
|
83
83
|
|
|
@@ -86,7 +86,7 @@ export class BsJsonInput {
|
|
|
86
86
|
// result = editorModule.renderJSONSchemaEnum(props, jsonSchema, this.#getSchemaDefinitions(jsonSchema));
|
|
87
87
|
// }
|
|
88
88
|
|
|
89
|
-
return
|
|
89
|
+
return editorModule!.renderValue(props);
|
|
90
90
|
};
|
|
91
91
|
|
|
92
92
|
onRenderMenu = (items: MenuItem[]): MenuItem[] | undefined => {
|
|
@@ -140,12 +140,12 @@ export class BsJsonInput {
|
|
|
140
140
|
return this.required && (this.value == null || this.value === '');
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
get schemaVersion(): string {
|
|
143
|
+
get schemaVersion(): string | undefined {
|
|
144
144
|
if (this.jsonSchema !== true) return undefined;
|
|
145
145
|
|
|
146
|
-
const
|
|
146
|
+
const value = this.value as JSONSchema;
|
|
147
147
|
|
|
148
|
-
return value == null || value
|
|
148
|
+
return value == null || value.$schema == null ? '' : (value.$schema as string);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
get validator(): Validator | undefined {
|
|
@@ -172,7 +172,7 @@ export class BsJsonInput {
|
|
|
172
172
|
// do not validate empty documents
|
|
173
173
|
if (json === undefined) return [];
|
|
174
174
|
|
|
175
|
-
void ajv.validateSchema(json);
|
|
175
|
+
void ajv.validateSchema(json as AnySchema);
|
|
176
176
|
|
|
177
177
|
return rawThis.#processErrorsAjv(ajv.errors, json);
|
|
178
178
|
};
|
|
@@ -244,7 +244,7 @@ export class BsJsonInput {
|
|
|
244
244
|
return (schema.$defs ?? schema.definitions) as JSONSchemaDefinitions;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
#processErrorsAjv(errors: ErrorObject[] | null, json: unknown): ValidationError[] {
|
|
247
|
+
#processErrorsAjv(errors: ErrorObject[] | null | undefined, json: unknown): ValidationError[] {
|
|
248
248
|
const message = this.jsonSchema === true ? 'JSON is not a valid JSONSchema' : 'JSON does not match schema';
|
|
249
249
|
|
|
250
250
|
this.input.setCustomValidity(errors?.length ? message : '');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './select-dropdown';
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
@import '@ekzo-dev/bootstrap/src/utils';
|
|
2
2
|
@import 'bootstrap/scss/forms/form-check';
|
|
3
3
|
|
|
4
|
-
bs-select
|
|
4
|
+
bs-select-dropdown {
|
|
5
|
+
display: block;
|
|
6
|
+
width: 100%;
|
|
7
|
+
|
|
5
8
|
.form-select {
|
|
6
9
|
cursor: default;
|
|
7
10
|
}
|
|
@@ -56,10 +59,10 @@ bs-select.addon {
|
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
/* stylelint-disable */
|
|
59
|
-
.was-validated bs-select
|
|
60
|
-
.was-validated bs-select
|
|
61
|
-
bs-select
|
|
62
|
-
bs-select
|
|
62
|
+
.was-validated bs-select-dropdown:has(.btn-close) .form-select:invalid,
|
|
63
|
+
.was-validated bs-select-dropdown:has(.btn-close) .form-select:valid,
|
|
64
|
+
bs-select-dropdown:has(.btn-close) .form-select.is-invalid,
|
|
65
|
+
bs-select-dropdown:has(.btn-close) .form-select.is-valid {
|
|
63
66
|
padding-right: 5.5rem !important;
|
|
64
67
|
|
|
65
68
|
+ .btn-close {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import template from './select.html';
|
|
1
|
+
import template from './select-dropdown.html';
|
|
2
2
|
|
|
3
|
-
import './select.scss';
|
|
3
|
+
import './select-dropdown.scss';
|
|
4
4
|
|
|
5
5
|
import type { Options } from '@popperjs/core';
|
|
6
6
|
import type { Tooltip } from 'bootstrap';
|
|
@@ -11,24 +11,22 @@ import {
|
|
|
11
11
|
BsDropdownItem,
|
|
12
12
|
BsDropdownMenu,
|
|
13
13
|
BsDropdownToggle,
|
|
14
|
-
BsSelect
|
|
14
|
+
BsSelect,
|
|
15
15
|
ISelectOption,
|
|
16
16
|
} from '@ekzo-dev/bootstrap';
|
|
17
|
-
import { bindable, customElement, ICustomElementViewModel,
|
|
17
|
+
import { bindable, customElement, ICustomElementViewModel, queueTask } from 'aurelia';
|
|
18
18
|
|
|
19
19
|
import { Filter } from './filter';
|
|
20
20
|
|
|
21
21
|
@customElement({
|
|
22
|
-
name: 'bs-select',
|
|
22
|
+
name: 'bs-select-dropdown',
|
|
23
23
|
template,
|
|
24
24
|
dependencies: [BsDropdown, BsDropdownMenu, BsDropdownToggle, BsDropdownItem, Filter, BsCloseButton],
|
|
25
25
|
})
|
|
26
|
-
export class
|
|
26
|
+
export class BsSelectDropdown extends BsSelect implements ICustomElementViewModel {
|
|
27
27
|
@bindable()
|
|
28
28
|
emptyValue?: unknown = null;
|
|
29
29
|
|
|
30
|
-
host = resolve(HTMLElement);
|
|
31
|
-
|
|
32
30
|
filter: string = '';
|
|
33
31
|
|
|
34
32
|
emptyOption?: ISelectOption;
|
|
@@ -36,8 +34,6 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
36
34
|
popperConfig: Partial<Options> | Tooltip.PopperConfigFunction | null = null;
|
|
37
35
|
|
|
38
36
|
binding() {
|
|
39
|
-
super.binding();
|
|
40
|
-
|
|
41
37
|
if (this.multiple && !Array.isArray(this.value)) {
|
|
42
38
|
this.value = [];
|
|
43
39
|
}
|
|
@@ -47,7 +43,7 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
47
43
|
this.setPopperConfig();
|
|
48
44
|
}
|
|
49
45
|
|
|
50
|
-
valueChanged(value: unknown)
|
|
46
|
+
valueChanged(value: unknown) {
|
|
51
47
|
if (this.multiple && !Array.isArray(value)) {
|
|
52
48
|
this.value = [];
|
|
53
49
|
}
|
|
@@ -62,7 +58,7 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
62
58
|
setPopperConfig() {
|
|
63
59
|
const { host } = this;
|
|
64
60
|
const parentModal = host.closest('.modal-body,.popover-body,.offcanvas-body');
|
|
65
|
-
const dropdownMenu: HTMLElement = host.querySelector('.dropdown-menu')
|
|
61
|
+
const dropdownMenu: HTMLElement = host.querySelector('.dropdown-menu')!;
|
|
66
62
|
|
|
67
63
|
if (parentModal != null) {
|
|
68
64
|
this.popperConfig = {
|
|
@@ -71,7 +67,7 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
71
67
|
dropdownMenu.style.minWidth = `${host.offsetWidth}px`;
|
|
72
68
|
} else {
|
|
73
69
|
this.popperConfig = null;
|
|
74
|
-
dropdownMenu.style.minWidth =
|
|
70
|
+
dropdownMenu.style.minWidth = '';
|
|
75
71
|
}
|
|
76
72
|
}
|
|
77
73
|
|
|
@@ -79,8 +75,8 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
79
75
|
return `${this.id}${parentIndex != null ? '-g' + parentIndex.toString() : ''}-${index}`;
|
|
80
76
|
}
|
|
81
77
|
|
|
82
|
-
selectOption(option
|
|
83
|
-
this.value = option
|
|
78
|
+
selectOption(option?: ISelectOption) {
|
|
79
|
+
this.value = option?.value;
|
|
84
80
|
this.#dispatchEvents();
|
|
85
81
|
}
|
|
86
82
|
|
|
@@ -89,7 +85,7 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
89
85
|
const { options, value } = this;
|
|
90
86
|
|
|
91
87
|
return Array.isArray(value)
|
|
92
|
-
? value.map((val) => (options as ISelectOption[]).find((option) => option.value === val)
|
|
88
|
+
? value.map((val) => (options as ISelectOption[]).find((option) => option.value === val)!.text).join(', ')
|
|
93
89
|
: '';
|
|
94
90
|
}
|
|
95
91
|
|
|
@@ -138,13 +134,16 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
138
134
|
options = Object.entries(options);
|
|
139
135
|
}
|
|
140
136
|
|
|
137
|
+
// @ts-ignore
|
|
141
138
|
const isEntries = Array.isArray(options[0]);
|
|
142
139
|
let option = (options as Array<ISelectOption | readonly [unknown, string]>).find((option) => {
|
|
140
|
+
// @ts-ignore
|
|
143
141
|
const optionValue: unknown = isEntries ? option[0] : (option as ISelectOption).value;
|
|
144
142
|
|
|
145
143
|
if (optionValue == emptyValue) {
|
|
146
144
|
emptyOption = {
|
|
147
145
|
value: optionValue,
|
|
146
|
+
// @ts-ignore
|
|
148
147
|
text: isEntries ? (option[1] as string) : (option as ISelectOption).text,
|
|
149
148
|
} as ISelectOption;
|
|
150
149
|
}
|
|
@@ -153,18 +152,19 @@ export class BsSelect extends BaseBsSelect implements ICustomElementViewModel {
|
|
|
153
152
|
});
|
|
154
153
|
|
|
155
154
|
option =
|
|
155
|
+
// @ts-ignore
|
|
156
156
|
isEntries && option !== undefined ? { value: option[0], text: option[1] as string } : (option as ISelectOption);
|
|
157
157
|
|
|
158
158
|
// update value next tick
|
|
159
159
|
const foundValue = option?.value;
|
|
160
160
|
|
|
161
161
|
if (foundValue !== value) {
|
|
162
|
-
|
|
163
|
-
void Promise.resolve().then(() => (this.value = foundValue));
|
|
162
|
+
queueTask(() => (this.value = foundValue));
|
|
164
163
|
}
|
|
165
164
|
|
|
166
165
|
// update empty option next tick
|
|
167
|
-
|
|
166
|
+
// TODO: investigate if next tick is still needed
|
|
167
|
+
queueTask(() => (this.emptyOption = emptyOption));
|
|
168
168
|
|
|
169
169
|
return option;
|
|
170
170
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// // import { BsButton, BsOffcanvas } from '@ekzo-dev/bootstrap';
|
|
2
|
+
// // import { extractArgTypes, Meta, Story } from '@storybook/aurelia';
|
|
3
|
+
// //
|
|
4
|
+
// // import { selectControl } from '../../../../../.storybook/helpers';
|
|
5
|
+
// //
|
|
6
|
+
// // import { BsSelectDropdown } from '.';
|
|
7
|
+
// //
|
|
8
|
+
// // export default {
|
|
9
|
+
// // title: 'Ekzo / Bootstrap Addons / Forms / Select',
|
|
10
|
+
// // component: BsSelectDropdown,
|
|
11
|
+
// // parameters: {
|
|
12
|
+
// // actions: {
|
|
13
|
+
// // handles: ['change', 'input'],
|
|
14
|
+
// // },
|
|
15
|
+
// // },
|
|
16
|
+
// // args: {
|
|
17
|
+
// // label: 'Label',
|
|
18
|
+
// // floatingLabel: false,
|
|
19
|
+
// // valid: null,
|
|
20
|
+
// // },
|
|
21
|
+
// // argTypes: {
|
|
22
|
+
// // bsSize: {
|
|
23
|
+
// // ...extractArgTypes(BsSelectDropdown).bsSize,
|
|
24
|
+
// // ...selectControl(['', 'sm', 'lg']),
|
|
25
|
+
// // },
|
|
26
|
+
// // },
|
|
27
|
+
// // } as Meta;
|
|
28
|
+
// //
|
|
29
|
+
// // const Overview: Story = (args) => ({
|
|
30
|
+
// // props: args,
|
|
31
|
+
// // });
|
|
32
|
+
// //
|
|
33
|
+
// // Overview.args = {
|
|
34
|
+
// // options: [
|
|
35
|
+
// // { value: undefined, text: 'Select option' },
|
|
36
|
+
// // { value: '1', text: 'One', disabled: true },
|
|
37
|
+
// // { value: '2', text: 'Two' },
|
|
38
|
+
// // { value: '3', text: 'Three', group: 'Group' },
|
|
39
|
+
// // ],
|
|
40
|
+
// // value: '2',
|
|
41
|
+
// // };
|
|
42
|
+
// //
|
|
43
|
+
// // const Multiple: Story = (args) => ({
|
|
44
|
+
// // props: args,
|
|
45
|
+
// // });
|
|
46
|
+
// //
|
|
47
|
+
// // Multiple.args = {
|
|
48
|
+
// // multiple: true,
|
|
49
|
+
// // value: ['2', '3'],
|
|
50
|
+
// // options: [
|
|
51
|
+
// // { value: '1', text: 'One', disabled: true },
|
|
52
|
+
// // { value: '2', text: 'Two' },
|
|
53
|
+
// // { value: '3', text: 'Three', group: 'Group' },
|
|
54
|
+
// // ],
|
|
55
|
+
// // };
|
|
56
|
+
// //
|
|
57
|
+
// // const LargeOptions: Story = (args) => ({
|
|
58
|
+
// // props: args,
|
|
59
|
+
// // template:
|
|
60
|
+
// // '<bs-select value.bind="value" options.bind="options" label.bind="label" style="width: 400px; max-width: 100%"></bs-select>',
|
|
61
|
+
// // });
|
|
62
|
+
// //
|
|
63
|
+
// // LargeOptions.args = {
|
|
64
|
+
// // options: Array.from({ length: 1000 }).map((v, i) => ({
|
|
65
|
+
// // value: i.toString(),
|
|
66
|
+
// // text: `Option ${i} has long content which forces dropdown menu to scale larger that select box`,
|
|
67
|
+
// // })),
|
|
68
|
+
// // };
|
|
69
|
+
// //
|
|
70
|
+
// // const InModal: Story = (args) => ({
|
|
71
|
+
// // props: args,
|
|
72
|
+
// // template: `
|
|
73
|
+
// // <button bs-button click.trigger="offcanvas.toggle()">Open modal</button>
|
|
74
|
+
// // <bs-offcanvas component.ref="offcanvas">
|
|
75
|
+
// // <bs-select value.bind="value" options.bind="options" label.bind="label" style="width: 100%"></bs-select>
|
|
76
|
+
// // <div style="height: 2000px"></div>
|
|
77
|
+
// // </bs-offcanvas>`,
|
|
78
|
+
// // components: [BsOffcanvas, BsButton],
|
|
79
|
+
// // });
|
|
80
|
+
// //
|
|
81
|
+
// // InModal.args = {
|
|
82
|
+
// // options: Array.from({ length: 1000 }).map((v, i) => ({
|
|
83
|
+
// // value: i.toString(),
|
|
84
|
+
// // text: `Option ${i} has long content which forces dropdown menu to scale larger that select box`,
|
|
85
|
+
// // })),
|
|
86
|
+
// // };
|
|
87
|
+
// //
|
|
88
|
+
// // // eslint-disable-next-line
|
|
89
|
+
// // export { Overview, Multiple, LargeOptions, InModal };
|
package/src/index.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './select';
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { BsButton, BsOffcanvas } from '@ekzo-dev/bootstrap';
|
|
2
|
-
import { extractArgTypes, Meta, Story } from '@storybook/aurelia';
|
|
3
|
-
|
|
4
|
-
import { selectControl } from '../../../../../.storybook/helpers';
|
|
5
|
-
|
|
6
|
-
import { BsSelect } from '.';
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
title: 'Ekzo / Bootstrap Addons / Forms / Select',
|
|
10
|
-
component: BsSelect,
|
|
11
|
-
parameters: {
|
|
12
|
-
actions: {
|
|
13
|
-
handles: ['change', 'input'],
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
args: {
|
|
17
|
-
label: 'Label',
|
|
18
|
-
floatingLabel: false,
|
|
19
|
-
valid: null,
|
|
20
|
-
},
|
|
21
|
-
argTypes: {
|
|
22
|
-
bsSize: {
|
|
23
|
-
...extractArgTypes(BsSelect).bsSize,
|
|
24
|
-
...selectControl(['', 'sm', 'lg']),
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
} as Meta;
|
|
28
|
-
|
|
29
|
-
const Overview: Story = (args) => ({
|
|
30
|
-
props: args,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
Overview.args = {
|
|
34
|
-
options: [
|
|
35
|
-
{ value: undefined, text: 'Select option' },
|
|
36
|
-
{ value: '1', text: 'One', disabled: true },
|
|
37
|
-
{ value: '2', text: 'Two' },
|
|
38
|
-
{ value: '3', text: 'Three', group: 'Group' },
|
|
39
|
-
],
|
|
40
|
-
value: '2',
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const Multiple: Story = (args) => ({
|
|
44
|
-
props: args,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
Multiple.args = {
|
|
48
|
-
multiple: true,
|
|
49
|
-
value: ['2', '3'],
|
|
50
|
-
options: [
|
|
51
|
-
{ value: '1', text: 'One', disabled: true },
|
|
52
|
-
{ value: '2', text: 'Two' },
|
|
53
|
-
{ value: '3', text: 'Three', group: 'Group' },
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const LargeOptions: Story = (args) => ({
|
|
58
|
-
props: args,
|
|
59
|
-
template:
|
|
60
|
-
'<bs-select value.bind="value" options.bind="options" label.bind="label" style="width: 400px; max-width: 100%"></bs-select>',
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
LargeOptions.args = {
|
|
64
|
-
options: Array.from({ length: 1000 }).map((v, i) => ({
|
|
65
|
-
value: i.toString(),
|
|
66
|
-
text: `Option ${i} has long content which forces dropdown menu to scale larger that select box`,
|
|
67
|
-
})),
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const InModal: Story = (args) => ({
|
|
71
|
-
props: args,
|
|
72
|
-
template: `
|
|
73
|
-
<button bs-button click.trigger="offcanvas.toggle()">Open modal</button>
|
|
74
|
-
<bs-offcanvas component.ref="offcanvas">
|
|
75
|
-
<bs-select value.bind="value" options.bind="options" label.bind="label" style="width: 100%"></bs-select>
|
|
76
|
-
<div style="height: 2000px"></div>
|
|
77
|
-
</bs-offcanvas>`,
|
|
78
|
-
components: [BsOffcanvas, BsButton],
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
InModal.args = {
|
|
82
|
-
options: Array.from({ length: 1000 }).map((v, i) => ({
|
|
83
|
-
value: i.toString(),
|
|
84
|
-
text: `Option ${i} has long content which forces dropdown menu to scale larger that select box`,
|
|
85
|
-
})),
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// eslint-disable-next-line
|
|
89
|
-
export { Overview, Multiple, LargeOptions, InModal };
|
|
File without changes
|
|
File without changes
|