native-document 1.0.261 → 1.0.263
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/elements.d.ts +1 -0
- package/elements.js +1 -0
- package/package.json +1 -1
- package/src/components/form/field/types/SelectField.js +6 -2
- package/src/components/modal/types/createModal.d.ts +1 -1
- package/src/core/elements/anchor/Slot.js +30 -0
- package/src/ui/components/form/fields/SelectFieldRender.js +29 -7
- package/types/slot.ts +75 -0
package/elements.d.ts
CHANGED
package/elements.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export {default as Anchor, default as NativeDocumentFragment } from "./src/core/elements/anchor/anchor";
|
|
2
|
+
export { default as Slot } from "./src/core/elements/anchor/Slot";
|
|
2
3
|
export { createPortal } from "./src/core/elements/anchor/anchor";
|
|
3
4
|
export * from './src/core/elements/index';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "native-document",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.263",
|
|
4
4
|
"description": "A reactive JavaScript framework that preserves native DOM simplicity without sacrificing modern features",
|
|
5
5
|
"author": "AfroCodeur <https://github.com/afrocodeur>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,6 +53,7 @@ export default function SelectField(name, props) {
|
|
|
53
53
|
selectedLabelRender: false,
|
|
54
54
|
renderItem: null,
|
|
55
55
|
truncateMax: null,
|
|
56
|
+
optionsMapper: null,
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -83,7 +84,8 @@ SelectField.defaultTemplate = null;
|
|
|
83
84
|
* hasErrors: Observable<boolean>,
|
|
84
85
|
* errors: Observable<string[]>,
|
|
85
86
|
* showErrors: Observable<boolean>,
|
|
86
|
-
* props: GlobalAttributes
|
|
87
|
+
* props: GlobalAttributes,
|
|
88
|
+
* optionsMapper: (item) => {value: string|number, label: NdChild},
|
|
87
89
|
* }, instance: SelectField) => NdChild} template
|
|
88
90
|
*/
|
|
89
91
|
SelectField.use = function(template) {
|
|
@@ -95,10 +97,12 @@ SelectField.prototype.constructor = SelectField;
|
|
|
95
97
|
|
|
96
98
|
/**
|
|
97
99
|
* @param {Array<{ value: *, label: NdChild, props?: GlobalAttributes }>} opts
|
|
100
|
+
* @param {(item) => {value: string, label: string}} mapper
|
|
98
101
|
* @returns {this}
|
|
99
102
|
*/
|
|
100
|
-
SelectField.prototype.options = function(opts) {
|
|
103
|
+
SelectField.prototype.options = function(opts, mapper) {
|
|
101
104
|
this.$description.options = opts;
|
|
105
|
+
this.$description.optionsMapper = mapper;
|
|
102
106
|
return this;
|
|
103
107
|
};
|
|
104
108
|
|
|
@@ -17,4 +17,4 @@ export type ModalInstance<TResult = any, TParams = any> = {
|
|
|
17
17
|
|
|
18
18
|
export declare function createModal<TResult = any, TParams = any>(
|
|
19
19
|
builder: (context: ModalBuilderContext<TResult, TParams>) => ValidChild | ModalInterface
|
|
20
|
-
):
|
|
20
|
+
): ModalInstance<TResult, TParams>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Anchor from './anchor';
|
|
2
|
+
import {NDElement} from '../../wrappers/NDElement';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default function Slot(content) {
|
|
6
|
+
if(!(this instanceof Slot)) {
|
|
7
|
+
return new Slot(content);
|
|
8
|
+
}
|
|
9
|
+
this.$anchor = Anchor();
|
|
10
|
+
|
|
11
|
+
content && this.$anchor.setContent(content);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Slot.prototype.toNdElement = function() {
|
|
16
|
+
return this.$anchor;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
Slot.prototype.set = function(value) {
|
|
20
|
+
this.$anchor.replaceContent(value);
|
|
21
|
+
return this;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Slot.prototype.clear = function() {
|
|
25
|
+
this.$anchor.clear();
|
|
26
|
+
return this;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
Slot.prototype.refSelf = NDElement.prototype.refSelf;
|
|
30
|
+
Slot.prototype.ref = NDElement.prototype.ref;
|
|
@@ -33,6 +33,26 @@ export default function SelectFieldRender($desc, instance) {
|
|
|
33
33
|
return Div(instance.resolveProps(), content).nd.with({input: nativeSelect});
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
const getUsableOption = ($desc, option) => {
|
|
37
|
+
if(option == null) {
|
|
38
|
+
option = { value: null, label: null};
|
|
39
|
+
}
|
|
40
|
+
else if($desc.optionsMapper) {
|
|
41
|
+
option = $desc.optionsMapper(option);
|
|
42
|
+
}
|
|
43
|
+
if(typeof option === 'string' || typeof option === 'number') {
|
|
44
|
+
option = { value: option, label: option };
|
|
45
|
+
}
|
|
46
|
+
return option;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const findUsableOption = ($desc, options, val) => {
|
|
50
|
+
return options.filter((option) => {
|
|
51
|
+
const optionsSource = getUsableOption($desc, option);
|
|
52
|
+
return optionsSource.value.valueOf() === val;
|
|
53
|
+
}).map((option) => getUsableOption($desc, option)).at(0);
|
|
54
|
+
};
|
|
55
|
+
|
|
36
56
|
const buildLabel = ($desc) => {
|
|
37
57
|
return Label({
|
|
38
58
|
class: 'field-label',
|
|
@@ -91,7 +111,7 @@ const buildTagsDisplay = ($desc) => {
|
|
|
91
111
|
|
|
92
112
|
return Div({class: 'select-field-tags'},
|
|
93
113
|
ForEachArray($desc.value, (val) => {
|
|
94
|
-
const opt =
|
|
114
|
+
const opt = findUsableOption($desc, options, val);
|
|
95
115
|
const label = opt?.label ?? opt ?? val;
|
|
96
116
|
|
|
97
117
|
const tag = Span({class: 'select-field-tag'}, [
|
|
@@ -133,7 +153,7 @@ const buildSelectedLabel = ($desc) => {
|
|
|
133
153
|
const options = $desc.options;
|
|
134
154
|
|
|
135
155
|
if(!$desc.multiple || !Array.isArray(val)) {
|
|
136
|
-
const opt =
|
|
156
|
+
const opt = findUsableOption($desc, options, val);
|
|
137
157
|
return opt?.label ?? opt ?? val;
|
|
138
158
|
}
|
|
139
159
|
|
|
@@ -144,7 +164,7 @@ const buildSelectedLabel = ($desc) => {
|
|
|
144
164
|
}
|
|
145
165
|
|
|
146
166
|
const labels = val.map(v => {
|
|
147
|
-
const opt =
|
|
167
|
+
const opt = findUsableOption($desc, options, v);
|
|
148
168
|
return opt?.label ?? opt ?? v;
|
|
149
169
|
});
|
|
150
170
|
|
|
@@ -175,8 +195,9 @@ const buildNativeSelect = ($desc) => {
|
|
|
175
195
|
multiple: $desc.multiple,
|
|
176
196
|
style: {display: 'none'},
|
|
177
197
|
}, ForEachArray($options, (option) => {
|
|
178
|
-
const
|
|
179
|
-
const
|
|
198
|
+
const optionSource = getUsableOption($desc, option);
|
|
199
|
+
const optValue = optionSource.value ?? option;
|
|
200
|
+
const optLabel = optionSource.label ?? option;
|
|
180
201
|
const optProps = option.props ?? {};
|
|
181
202
|
return Option({value: optValue, ...optProps}, optLabel);
|
|
182
203
|
}));
|
|
@@ -224,8 +245,9 @@ const buildDropdown = ($desc, instance, trigger, nativeSelect) => {
|
|
|
224
245
|
}
|
|
225
246
|
|
|
226
247
|
return dropdown.bind($sourceItem, (option) => {
|
|
227
|
-
const
|
|
228
|
-
const
|
|
248
|
+
const optionSource = getUsableOption($desc, option);
|
|
249
|
+
const optValue = optionSource.value ?? option;
|
|
250
|
+
const optLabel = optionSource.label ?? option;
|
|
229
251
|
|
|
230
252
|
const $isSelected = $desc.value?.__$isObservable
|
|
231
253
|
? $desc.value.is(v => $desc.multiple
|
package/types/slot.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {AnchorDocumentFragment, ValidChild} from "./elements";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A dynamic content slot backed by an Anchor.
|
|
6
|
+
* Allows replacing, clearing and referencing a zone of the DOM
|
|
7
|
+
* without re-rendering the surrounding structure.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const slot = Slot(Div('Initial content'));
|
|
11
|
+
*
|
|
12
|
+
* // Replace content
|
|
13
|
+
* slot.set(Div('New content'));
|
|
14
|
+
*
|
|
15
|
+
* // Clear content
|
|
16
|
+
* slot.clear();
|
|
17
|
+
*
|
|
18
|
+
* // Store reference
|
|
19
|
+
* const refs = { content: null };
|
|
20
|
+
* slot.refSelf(refs, 'content');
|
|
21
|
+
* refs.content.set(Div('Updated'));
|
|
22
|
+
*/
|
|
23
|
+
export interface SlotInterface {
|
|
24
|
+
/** Internal anchor managing the DOM zone. */
|
|
25
|
+
readonly $anchor: AnchorDocumentFragment;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Replaces the current content of the slot.
|
|
29
|
+
*
|
|
30
|
+
* @param value - New content to display
|
|
31
|
+
*/
|
|
32
|
+
set(value: ValidChild): this;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Clears the slot content.
|
|
36
|
+
*/
|
|
37
|
+
clear(): this;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Stores the native DOM node reference in an object under the given key.
|
|
41
|
+
*
|
|
42
|
+
* @param target - Object to store the reference in
|
|
43
|
+
* @param key - Key to assign the reference to
|
|
44
|
+
*/
|
|
45
|
+
ref<T extends object>(target: T, key: keyof T): this;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Stores the SlotInterface instance itself in an object under the given key.
|
|
49
|
+
*
|
|
50
|
+
* @param target - Object to store the reference in
|
|
51
|
+
* @param key - Key to assign the reference to
|
|
52
|
+
*/
|
|
53
|
+
refSelf<T extends object>(target: T, key: keyof T): this;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns the underlying Anchor element for DOM insertion.
|
|
57
|
+
* Called automatically by NativeDocument when the Slot is used as a child.
|
|
58
|
+
*/
|
|
59
|
+
toNdElement(): AnchorDocumentFragment;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a dynamic content slot — a named zone of the DOM that can be
|
|
64
|
+
* replaced or cleared independently of its surroundings.
|
|
65
|
+
*
|
|
66
|
+
* @param content - Optional initial content
|
|
67
|
+
* @returns SlotInterface instance
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* const $header = Slot(H1('Welcome'));
|
|
71
|
+
*
|
|
72
|
+
* // Later
|
|
73
|
+
* $header.set(H1('Dashboard'));
|
|
74
|
+
*/
|
|
75
|
+
export declare function Slot(content?: ValidChild): SlotInterface;
|