asljs-ui-list 0.0.0-stage → 0.1.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/LICENSE.md ADDED
@@ -0,0 +1,51 @@
1
+ # Permissive No-Derivatives License 1.0
2
+
3
+ Copyright (c) 2026 Alexandrite Software Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software (the "Software") to:
7
+
8
+ 1. Use the Software for any purpose, including commercial purposes.
9
+ 2. Copy and redistribute the Software, including as part of another application,
10
+ library, or package.
11
+ 3. Modify the Software for private or internal use.
12
+
13
+ Subject to the following conditions:
14
+
15
+ ## 1. No Distribution of Modified Versions
16
+
17
+ Modified versions of the Software, or substantial portions thereof, must not be
18
+ distributed without prior written permission from the copyright holder.
19
+
20
+ Routine build transformations, including minification, transpilation, and
21
+ bundling, are permitted for distribution, provided they do not intentionally
22
+ alter the Software's functionality.
23
+
24
+ ## 2. Licence and Copyright Preservation
25
+
26
+ All distributed copies of the Software must retain this copyright notice and
27
+ licence.
28
+
29
+ The Software itself, including copies incorporated into other applications,
30
+ libraries, or packages, remains subject to this licence.
31
+
32
+ The Software must not be sublicensed or redistributed under a different licence.
33
+
34
+ ## 3. Use in Other Software
35
+
36
+ Applications and libraries that merely use, import, link to, or bundle the
37
+ Software are not considered modified versions of the Software and may be
38
+ distributed under any licence.
39
+
40
+ Such use, incorporation, or bundling does not grant permission to relicense the
41
+ Software or distribute modified versions of it.
42
+
43
+ ### 4. No Warranty
44
+
45
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
47
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+
49
+ IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR
50
+ OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR ITS
51
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,82 @@
1
- # Temporary Holding Version
1
+ # list
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Part of [Alexandrite Software Library][#1] - a set of high-quality, performant
4
+ > JavaScript libraries and tools for everyday use.
5
+
6
+ ## Overview
7
+
8
+ `asljs-ui-list` provides `asljs-list`, which renders a collection from
9
+ templates. Each row is bound with `asljs-data-binding` to its own context: the
10
+ item, its position, and the shared `context` of row actions.
11
+
12
+ ## Scope
13
+
14
+ - Items as a plain array or an eventful-like collection the list re-renders from
15
+ when it changes.
16
+ - Row, empty-state and container templates, local or from the `list` theme
17
+ section; `createBootstrapListTheme()` supplies a Bootstrap list group.
18
+ - Render callbacks and inline call expressions are outside the model: rows come
19
+ from templates and handlers are binding paths.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install asljs-ui-list
25
+ ```
26
+
27
+ NPM package: [asljs-ui-list][NPM]
28
+
29
+ ## Usage
30
+
31
+ Import the package once to register the element:
32
+
33
+ ```ts
34
+ import 'asljs-ui-list';
35
+
36
+ const list =
37
+ document.createElement('asljs-list');
38
+
39
+ list.context = {
40
+ select(this: { item: { title: string } }) {
41
+ console.log('selected', this.item.title);
42
+ }
43
+ };
44
+
45
+ list.innerHTML = `
46
+ <template data-slot="item">
47
+ <a data-bind-text="item.title"
48
+ data-bind-on-click="context.select"></a>
49
+ </template>
50
+ `;
51
+
52
+ list.items =
53
+ [ { title: 'First' },
54
+ { title: 'Second' } ];
55
+
56
+ document.body.appendChild(list);
57
+ ```
58
+
59
+ ## Further reading
60
+
61
+ - [List][DOC] - templates, the row binding context and row actions.
62
+ - [Theming][THM] - templates, themes and how they combine.
63
+
64
+ Questions and bugs: [asljs/issues][ISS].
65
+
66
+ ## Related packages
67
+
68
+ - [ui][UI] - the shared theme and the other UI packages.
69
+ - `asljs-data-binding` for the bindings the row templates use.
70
+ - `asljs-eventful` for the collections the list follows.
71
+
72
+ ## License
73
+
74
+ MIT License. See [LICENSE][LIC] for details.
75
+
76
+ [#1]: https://github.com/AlexandriteSoftware/asljs
77
+ [DOC]: docs/List.md
78
+ [ISS]: https://github.com/AlexandriteSoftware/asljs/issues
79
+ [LIC]: LICENSE.md
80
+ [NPM]: https://www.npmjs.com/package/asljs-ui-list
81
+ [THM]: ../core/docs/Theming.md
82
+ [UI]: ../core/README.md
@@ -0,0 +1,2 @@
1
+ export { List, ListModelDefinition, type ListItem, type ListItemsSource, type ListRowContext } from './list.js';
2
+ export { createBootstrapListTheme, type ListThemeDefinition } from './theme.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { List, ListModelDefinition } from './list.js';
2
+ export { createBootstrapListTheme } from './theme.js';
package/dist/list.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { ComponentModelDefinition, ComponentsTheme } from 'asljs-ui';
2
+ import { LitElement } from 'lit';
3
+ export type ListRowContext = {
4
+ item: ListItem;
5
+ index: number;
6
+ context: unknown;
7
+ first: boolean;
8
+ last: boolean;
9
+ odd: boolean;
10
+ even: boolean;
11
+ count: number;
12
+ };
13
+ export type ListItem = Record<string, unknown>;
14
+ export type ListItemsSource = ListItem[];
15
+ export declare const ListModelDefinition: ComponentModelDefinition;
16
+ export declare class List extends LitElement {
17
+ #private;
18
+ accessor items: ListItemsSource;
19
+ accessor context: unknown;
20
+ accessor theme: ComponentsTheme | null;
21
+ createRenderRoot(): this;
22
+ connectedCallback(): void;
23
+ disconnectedCallback(): void;
24
+ render(): ReturnType<LitElement['render']>;
25
+ updated(changedProperties: Map<PropertyKey, unknown>): void;
26
+ }
package/dist/list.js ADDED
@@ -0,0 +1,313 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { bindDataModel } from 'asljs-data-binding';
8
+ import { asEventfulLike } from 'asljs-eventful';
9
+ import { defineComponentModel, findThemeProvider, getDefaultTheme, resolveThemeTemplate, THEME_CHANGED_EVENT_NAME } from 'asljs-ui';
10
+ import { html, LitElement, nothing } from 'lit';
11
+ import { customElement, property } from 'lit/decorators.js';
12
+ export const ListModelDefinition = { name: 'ListModelDefinition',
13
+ title: 'List',
14
+ properties: [{ name: 'items',
15
+ title: 'Items',
16
+ type: 'array',
17
+ description: 'Rows rendered by the list.' },
18
+ { name: 'context',
19
+ title: 'Context',
20
+ type: 'object',
21
+ description: 'Shared row binding context.' },
22
+ { name: 'theme',
23
+ title: 'Theme',
24
+ type: 'object',
25
+ description: 'Per-instance components theme override.' }] };
26
+ defineComponentModel('asljs-list', ListModelDefinition);
27
+ let List = class List extends LitElement {
28
+ #containerTemplate = null;
29
+ #emptyTemplate = null;
30
+ #itemTemplate = null;
31
+ #itemBindingDisposers = [];
32
+ #itemsObserverDispose = null;
33
+ #themeProvider = null;
34
+ #warnedMissingItemTemplate = false;
35
+ #warnedInvalidContainer = false;
36
+ #handleThemeChanged = () => {
37
+ this.requestUpdate();
38
+ };
39
+ #items_accessor_storage = [];
40
+ get items() { return this.#items_accessor_storage; }
41
+ set items(value) { this.#items_accessor_storage = value; }
42
+ #context_accessor_storage = undefined;
43
+ get context() { return this.#context_accessor_storage; }
44
+ set context(value) { this.#context_accessor_storage = value; }
45
+ #theme_accessor_storage = null;
46
+ get theme() { return this.#theme_accessor_storage; }
47
+ set theme(value) { this.#theme_accessor_storage = value; }
48
+ createRenderRoot() {
49
+ return this;
50
+ }
51
+ connectedCallback() {
52
+ super.connectedCallback();
53
+ this.#captureTemplates();
54
+ this.#syncItemsObserver();
55
+ this.#syncThemeProvider();
56
+ }
57
+ disconnectedCallback() {
58
+ this.#disposeItemsObserver();
59
+ this.#disposeItemBindings();
60
+ this.#disposeThemeProvider();
61
+ super.disconnectedCallback();
62
+ }
63
+ render() {
64
+ const emptyTemplate = this.#resolveTemplate('empty');
65
+ const itemTemplate = this.#resolveTemplate('item');
66
+ const containerTemplate = this.#resolveTemplate('container');
67
+ if (this.items.length === 0) {
68
+ if (emptyTemplate) {
69
+ return html `
70
+ <div data-role="empty-template-host"></div>
71
+ `;
72
+ }
73
+ return nothing;
74
+ }
75
+ if (!itemTemplate) {
76
+ return nothing;
77
+ }
78
+ if (containerTemplate) {
79
+ return html `
80
+ <div data-role="container-template-host"></div>
81
+ `;
82
+ }
83
+ return html `
84
+ <div data-role="default-container-host">
85
+ </div>
86
+ `;
87
+ }
88
+ updated(changedProperties) {
89
+ if (changedProperties.has('items')) {
90
+ this.#syncItemsObserver();
91
+ }
92
+ if (changedProperties.has('theme')) {
93
+ this.#syncThemeProvider();
94
+ }
95
+ this.#renderTemplateContent();
96
+ }
97
+ #captureTemplates() {
98
+ this.#containerTemplate = null;
99
+ this.#emptyTemplate = null;
100
+ this.#itemTemplate = null;
101
+ this.#warnedMissingItemTemplate = false;
102
+ this.#warnedInvalidContainer = false;
103
+ const templateElements = this.querySelectorAll('template[data-slot]');
104
+ for (const item of templateElements) {
105
+ const templateElement = item;
106
+ const slotName = templateElement.getAttribute('data-slot');
107
+ const clonedTemplate = document.createElement('template');
108
+ clonedTemplate.content.append(templateElement.content.cloneNode(true));
109
+ if (slotName === 'empty') {
110
+ this.#emptyTemplate = clonedTemplate;
111
+ }
112
+ if (slotName === 'item') {
113
+ this.#itemTemplate = clonedTemplate;
114
+ }
115
+ if (slotName === 'container') {
116
+ this.#containerTemplate = clonedTemplate;
117
+ }
118
+ }
119
+ }
120
+ #renderTemplateContent() {
121
+ this.#renderEmptyTemplate();
122
+ this.#renderItemTemplates();
123
+ }
124
+ #renderEmptyTemplate() {
125
+ const emptyTemplate = this.#resolveTemplate('empty');
126
+ if (!emptyTemplate
127
+ || this.items.length > 0) {
128
+ return;
129
+ }
130
+ const host = this.querySelector('[data-role="empty-template-host"]');
131
+ if (!host) {
132
+ return;
133
+ }
134
+ host.replaceChildren(emptyTemplate.content.cloneNode(true));
135
+ }
136
+ #renderItemTemplates() {
137
+ this.#disposeItemBindings();
138
+ const itemTemplate = this.#resolveTemplate('item');
139
+ if (!itemTemplate
140
+ || this.items.length === 0) {
141
+ if (!itemTemplate
142
+ && this.items.length > 0) {
143
+ this.#warnMissingItemTemplate();
144
+ }
145
+ return;
146
+ }
147
+ const itemsHost = this.#resolveItemsHost();
148
+ if (!itemsHost) {
149
+ return;
150
+ }
151
+ const rowNodes = [];
152
+ const count = this.items.length;
153
+ for (let index = 0; index < this.items.length; index++) {
154
+ const item = this.items[index];
155
+ const rowContext = { item,
156
+ index,
157
+ context: this.#createRowScopeContext(item, index),
158
+ first: index === 0,
159
+ last: index === count - 1,
160
+ odd: index % 2 === 1,
161
+ even: index % 2 === 0,
162
+ count };
163
+ const fragment = itemTemplate.content.cloneNode(true);
164
+ this.#bindFragmentModel(fragment, rowContext);
165
+ rowNodes.push(...[...fragment.childNodes]);
166
+ }
167
+ itemsHost.replaceChildren(...rowNodes);
168
+ }
169
+ #resolveItemsHost() {
170
+ const containerTemplate = this.#resolveTemplate('container');
171
+ if (containerTemplate) {
172
+ const containerHost = this.querySelector('[data-role="container-template-host"]');
173
+ if (!containerHost) {
174
+ return null;
175
+ }
176
+ const fragment = containerTemplate.content.cloneNode(true);
177
+ const templatedItemsHost = fragment.querySelector('[data-role="items"]');
178
+ containerHost.replaceChildren(fragment);
179
+ if (!templatedItemsHost) {
180
+ this.#warnInvalidContainer();
181
+ return null;
182
+ }
183
+ return templatedItemsHost;
184
+ }
185
+ const defaultContainerHost = this.querySelector('[data-role="default-container-host"]');
186
+ return defaultContainerHost;
187
+ }
188
+ #resolveTemplate(slotName) {
189
+ return this.#getLocalTemplate(slotName)
190
+ ?? this.#getThemeTemplate(slotName);
191
+ }
192
+ #getLocalTemplate(slotName) {
193
+ if (slotName === 'container') {
194
+ return this.#containerTemplate;
195
+ }
196
+ if (slotName === 'empty') {
197
+ return this.#emptyTemplate;
198
+ }
199
+ return this.#itemTemplate;
200
+ }
201
+ #getThemeTemplate(slotName) {
202
+ const activeTheme = this.theme
203
+ ?? this.#themeProvider?.theme
204
+ ?? getDefaultTheme();
205
+ return resolveThemeTemplate(activeTheme.list?.[slotName], this);
206
+ }
207
+ #bindFragmentModel(fragment, model) {
208
+ const dispose = bindDataModel(fragment, model);
209
+ this.#itemBindingDisposers.push(dispose);
210
+ }
211
+ #createRowScopeContext(item, index) {
212
+ if (this.context === null
213
+ || this.context === undefined
214
+ || typeof this.context
215
+ !== 'object') {
216
+ return this.context;
217
+ }
218
+ const baseContext = this.context;
219
+ const rowContext = Object.create(baseContext);
220
+ rowContext.item = item;
221
+ rowContext.index = index;
222
+ for (const key of Object.keys(baseContext)) {
223
+ const value = baseContext[key];
224
+ if (typeof value
225
+ === 'function') {
226
+ rowContext[key] =
227
+ value.bind(rowContext);
228
+ }
229
+ }
230
+ return rowContext;
231
+ }
232
+ #disposeItemBindings() {
233
+ for (const dispose of this.#itemBindingDisposers) {
234
+ dispose();
235
+ }
236
+ this.#itemBindingDisposers = [];
237
+ }
238
+ #syncItemsObserver() {
239
+ this.#disposeItemsObserver();
240
+ const eventSource = toEventfulLike(this.items);
241
+ if (!eventSource) {
242
+ return;
243
+ }
244
+ const unsubscribers = [];
245
+ const onCollectionChanged = () => {
246
+ this.requestUpdate();
247
+ };
248
+ // An observable collection reports every change as one `change` event,
249
+ // carrying the list of what changed; the list re-reads it all anyway.
250
+ const unsubscribe = eventSource.on('change', onCollectionChanged);
251
+ unsubscribers.push(() => {
252
+ unsubscribe();
253
+ });
254
+ this.#itemsObserverDispose =
255
+ () => {
256
+ for (const unsubscribe of unsubscribers) {
257
+ unsubscribe();
258
+ }
259
+ };
260
+ }
261
+ #disposeItemsObserver() {
262
+ if (this.#itemsObserverDispose) {
263
+ this.#itemsObserverDispose();
264
+ this.#itemsObserverDispose = null;
265
+ }
266
+ }
267
+ #syncThemeProvider() {
268
+ const nextProvider = this.theme
269
+ ? null
270
+ : findThemeProvider(this);
271
+ if (this.#themeProvider === nextProvider) {
272
+ return;
273
+ }
274
+ this.#disposeThemeProvider();
275
+ this.#themeProvider = nextProvider;
276
+ this.#themeProvider?.addEventListener(THEME_CHANGED_EVENT_NAME, this.#handleThemeChanged);
277
+ }
278
+ #disposeThemeProvider() {
279
+ this.#themeProvider?.removeEventListener(THEME_CHANGED_EVENT_NAME, this.#handleThemeChanged);
280
+ this.#themeProvider = null;
281
+ }
282
+ #warnMissingItemTemplate() {
283
+ if (this.#warnedMissingItemTemplate) {
284
+ return;
285
+ }
286
+ this.#warnedMissingItemTemplate = true;
287
+ console.warn('asljs-list: missing required template[data-slot="item"] for non-empty items.');
288
+ }
289
+ #warnInvalidContainer() {
290
+ if (this.#warnedInvalidContainer) {
291
+ return;
292
+ }
293
+ this.#warnedInvalidContainer = true;
294
+ console.warn('asljs-list: container template must include [data-role="items"].');
295
+ }
296
+ };
297
+ __decorate([
298
+ property({ attribute: false })
299
+ ], List.prototype, "items", null);
300
+ __decorate([
301
+ property({ attribute: false })
302
+ ], List.prototype, "context", null);
303
+ __decorate([
304
+ property({ attribute: false })
305
+ ], List.prototype, "theme", null);
306
+ List = __decorate([
307
+ customElement('asljs-list')
308
+ ], List);
309
+ export { List };
310
+ function toEventfulLike(value) {
311
+ return asEventfulLike(value)
312
+ ?? null;
313
+ }
@@ -0,0 +1,13 @@
1
+ import { type ComponentsTheme, type ThemeTemplateValue } from 'asljs-ui';
2
+ export interface ListThemeDefinition {
3
+ container?: ThemeTemplateValue;
4
+ empty?: ThemeTemplateValue;
5
+ item?: ThemeTemplateValue;
6
+ }
7
+ declare module 'asljs-ui' {
8
+ interface ComponentsTheme {
9
+ list?: ListThemeDefinition;
10
+ }
11
+ }
12
+ /** The Bootstrap list section. */
13
+ export declare function createBootstrapListTheme(): ComponentsTheme;
package/dist/theme.js ADDED
@@ -0,0 +1,4 @@
1
+ /** The Bootstrap list section. */
2
+ export function createBootstrapListTheme() {
3
+ return { list: { container: '<div class="list-group" data-role="items"></div>' } };
4
+ }
package/docs/List.md ADDED
@@ -0,0 +1,106 @@
1
+ # List
2
+
3
+ `asljs-list` renders a collection from templates, binding each row to its own
4
+ context.
5
+
6
+ ## Properties
7
+
8
+ - `items` — a plain array, or an eventful-like collection the list re-renders
9
+ from when it changes
10
+ - `context` — shared row actions and state
11
+ - `theme`
12
+ - local slot templates
13
+
14
+ ## Templates
15
+
16
+ - `template[data-slot="item"]` — required; renders each row
17
+ - `template[data-slot="empty"]` — optional; the empty state
18
+ - `template[data-slot="container"]` — optional; must contain a
19
+ `[data-role="items"]` insertion point
20
+
21
+ If `items` is non-empty and no item template is provided, the component warns
22
+ and renders nothing. Themes can supply fallback templates; local templates
23
+ always win. The theme section is `list`; `createBootstrapListTheme()` supplies
24
+ Bootstrap list-group markup. See [Theming][THM].
25
+
26
+ ## Row binding context
27
+
28
+ Each row is bound with `asljs-data-binding` to a row context with these fields:
29
+
30
+ - `item`: the current row record
31
+ - `index`: the zero-based row index
32
+ - `first`: `true` for the first row
33
+ - `last`: `true` for the last row
34
+ - `odd`: `true` for odd row positions
35
+ - `even`: `true` for even row positions
36
+ - `count`: the total item count
37
+ - `context`: the shared base context, adapted to the current row
38
+
39
+ ## Row actions
40
+
41
+ - Reference shared actions through the row context, for example
42
+ `data-bind-on-click="context.select"`.
43
+ - Row-specific values arrive through the derived row-local `this`, which
44
+ includes row fields such as `item` and `index`.
45
+ - Arguments are not written in attributes: `select(item.id)` is not a binding.
46
+
47
+ ```ts
48
+ import 'asljs-ui-list';
49
+
50
+ const list =
51
+ document.createElement('asljs-list');
52
+
53
+ list.context = {
54
+ select(this: { item: { id: string; title: string } }, event: Event) {
55
+ event.preventDefault();
56
+ console.log('selected', this.item.id, this.item.title);
57
+ }
58
+ };
59
+
60
+ list.innerHTML = `
61
+ <template data-slot="container">
62
+ <section class="rows" data-role="items"></section>
63
+ </template>
64
+
65
+ <template data-slot="empty">
66
+ <div>No items</div>
67
+ </template>
68
+
69
+ <template data-slot="item">
70
+ <div>
71
+ <a data-bind-href="item.url"
72
+ data-bind-text="item.title"
73
+ data-bind-on-click="context.select"></a>
74
+ <small data-bind-text="index"></small>
75
+ </div>
76
+ </template>
77
+ `;
78
+
79
+ list.items =
80
+ [ { title: 'First', url: '/first' },
81
+ { title: 'Second', url: '/second' } ];
82
+ ```
83
+
84
+ ## Authoring rules
85
+
86
+ Rendering is template-driven. That shapes how a list is written:
87
+
88
+ - Rows come from templates, not from React-style render callbacks or prop-driven
89
+ row renderers.
90
+ - Bindings are `asljs-data-binding` paths, not template expressions with inline
91
+ function calls, and event handlers follow its path-based rules.
92
+ - Only the documented slots are used, and a container template must keep its
93
+ `[data-role="items"]` insertion point.
94
+ - Keep row templates declarative, and use `context` methods for shared row
95
+ actions rather than custom attribute protocols.
96
+ - Do not mutate slot templates at runtime. Update `list.items`, or the source
97
+ collection, instead of rewriting row DOM.
98
+
99
+ ## Exports
100
+
101
+ - `List` and `ListModelDefinition`
102
+ - `ListItem`, `ListItemsSource` and `ListRowContext` types
103
+ - `createBootstrapListTheme()` and the `ListThemeDefinition` type; the shared
104
+ theming exports of `asljs-ui` are listed in [Theming][THM]
105
+
106
+ [THM]: ../../core/docs/Theming.md
package/package.json CHANGED
@@ -1,6 +1,65 @@
1
1
  {
2
2
  "name": "asljs-ui-list",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "A web component that renders a collection from templates.",
5
+ "type": "module",
6
+ "asljs": {
7
+ "type": "lib"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist/**",
19
+ "README.md",
20
+ "LICENSE.md",
21
+ "docs/**"
22
+ ],
23
+ "scripts": {
24
+ "flint": "toolkit flint",
25
+ "clean": "toolkit clean",
26
+ "build": "npm run codegen --if-present && tsc -p tsconfig.build.json",
27
+ "build:dist": "npm run codegen --if-present && tsc -p tsconfig.dist.json",
28
+ "typecheck": "npm run codegen --if-present && tsc -p tsconfig.build.json --noEmit",
29
+ "guard:clean-git": "toolkit ensure-clean-working-directory",
30
+ "prepack": "npm run clean && npm run build:dist && npm run build && npm run test && npm run guard:clean-git",
31
+ "postpublish": "toolkit tag-release-revision",
32
+ "test": "node --test --enable-source-maps \"build/**/*.test.js\"",
33
+ "test:watch": "node --watch --test \"build/**/*.test.js\"",
34
+ "coverage": "npm run build && node --test --experimental-test-coverage --enable-source-maps --test-coverage-exclude=\"**/*.test.js\" \"build/**/*.test.js\"",
35
+ "release:patch": "toolkit release-patch",
36
+ "all": "npm run clean && npm run build:dist && npm run flint && npm run typecheck && npm run build && npm run test"
37
+ },
38
+ "keywords": [
39
+ "web-components",
40
+ "lit",
41
+ "ui",
42
+ "list"
43
+ ],
44
+ "author": "\"Alex Netkachov\" <alex.netkachov@gmail.com>",
45
+ "license": "SEE LICENSE IN LICENSE.md",
46
+ "homepage": "https://github.com/AlexandriteSoftware/asljs#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/AlexandriteSoftware/asljs/issues"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/AlexandriteSoftware/asljs.git"
53
+ },
54
+ "dependencies": {
55
+ "asljs-data-binding": "^0.2.5",
56
+ "asljs-eventful": "^0.4.11",
57
+ "asljs-ui": "^0.1.1",
58
+ "lit": "^3.3.1"
59
+ },
60
+ "devDependencies": {
61
+ "asljs-observable": "^0.5.5",
62
+ "asljs-testing": "^0.1.1",
63
+ "asljs-toolkit": "^0.1.0"
64
+ }
65
+ }