@htmlplus/element 3.3.1 → 3.4.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/dist/client.d.ts CHANGED
@@ -141,17 +141,9 @@ declare function Listen(type: string, options?: ListenOptions): (target: HTMLPlu
141
141
  */
142
142
  declare function Method(): (target: HTMLPlusElement, key: PropertyKey, _descriptor: PropertyDescriptor) => void;
143
143
 
144
- type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
145
- type Overwrite<T, U> = DistributiveOmit<T, keyof U> & U;
146
- type GenerateStringUnion<T> = Extract<{
147
- [Key in keyof T]: true extends T[Key] ? Key : never;
148
- }[keyof T], string>;
149
- type OverridesConfigBreakpointCreator<T extends string, U> = GenerateStringUnion<Overwrite<Record<T, true>, U>>;
150
- type OverridesConfig<Breakpoint extends string, Properties> = {
144
+ type OverridesConfig<Breakpoint extends string, Properties = unknown> = {
151
145
  [Key in Breakpoint]?: Partial<Properties>;
152
146
  };
153
- interface ElementPropertiesAutoGenerated {
154
- }
155
147
  declare function Overrides(): (target: HTMLPlusElement, key: string) => void;
156
148
 
157
149
  /**
@@ -215,6 +207,8 @@ declare function State(): (target: HTMLPlusElement, key: PropertyKey) => void;
215
207
 
216
208
  declare function Style(): (target: HTMLPlusElement, key: PropertyKey) => void;
217
209
 
210
+ declare function Variant(): (target: HTMLPlusElement, key: string) => void;
211
+
218
212
  /**
219
213
  * Monitors `@Property` and `@State` to detect changes.
220
214
  * The decorated method will be called after any changes,
@@ -255,6 +249,13 @@ interface Config {
255
249
  default?: unknown;
256
250
  };
257
251
  };
252
+ variants?: {
253
+ [key: string]: {
254
+ properties: {
255
+ [key: string]: unknown;
256
+ };
257
+ };
258
+ };
258
259
  };
259
260
  };
260
261
  }
@@ -319,6 +320,8 @@ declare const host: (target: HTMLElement | HTMLPlusElement) => HTMLElement;
319
320
  */
320
321
  declare const isCSSColor: (input: string) => boolean;
321
322
 
323
+ declare const isCSSUnit: (input: string) => boolean;
324
+
322
325
  /**
323
326
  * Indicates whether the direction of the element is `Right-To-Left` or not.
324
327
  */
@@ -342,10 +345,6 @@ type Slots = {
342
345
  */
343
346
  declare const slots: (target: HTMLElement | HTMLPlusElement) => Slots;
344
347
 
345
- declare const toCSSColor: (input: string) => string | undefined;
346
-
347
- declare const toCSSUnit: (input?: number | string | null) => string | undefined;
348
-
349
348
  /**
350
349
  * Converts a value to a unit.
351
350
  */
@@ -365,6 +364,12 @@ declare class Hole {
365
364
  values: any;
366
365
  }
367
366
 
367
+ type OverridableValue<Base, Overrides = unknown> = Exclude<Base, {
368
+ [K in keyof Overrides]: Overrides[K] extends false ? K : never;
369
+ }[keyof Overrides]> | {
370
+ [K in keyof Overrides]: Overrides[K] extends true ? K : never;
371
+ }[keyof Overrides];
372
+
368
373
  declare const attributes: (target: HTMLElement | HTMLPlusElement, attributes: unknown[]) => void;
369
374
  declare const html: ((template: any, ...values: any[]) => Hole) & {
370
375
  for(ref: any, id: any): any;
@@ -372,5 +377,5 @@ declare const html: ((template: any, ...values: any[]) => Hole) & {
372
377
  };
373
378
  declare const styles: (input: object) => string;
374
379
 
375
- export { Bind, Consumer, Debounce, Direction$1 as Direction, Element$1 as Element, Event, Host, IsRTL, Listen, Method, Overrides, Property, Provider, Query, QueryAll, Slots$1 as Slots, State, Style, Watch, attributes as a, classes, direction, dispatch, getConfig, getConfigCreator, html as h, host, isCSSColor, isRTL, off, on, query, queryAll, styles as s, setConfig, setConfigCreator, slots, toCSSColor, toCSSUnit, toUnit };
376
- export type { Config, ConfigOptions, ElementPropertiesAutoGenerated, EventEmitter, EventOptions, ListenOptions, OverridesConfig, OverridesConfigBreakpointCreator, PropertyOptions };
380
+ export { Bind, Consumer, Debounce, Direction$1 as Direction, Element$1 as Element, Event, Host, IsRTL, Listen, Method, Overrides, Property, Provider, Query, QueryAll, Slots$1 as Slots, State, Style, Variant, Watch, attributes as a, classes, direction, dispatch, getConfig, getConfigCreator, html as h, host, isCSSColor, isCSSUnit, isRTL, off, on, query, queryAll, styles as s, setConfig, setConfigCreator, slots, toUnit };
381
+ export type { Config, ConfigOptions, EventEmitter, EventOptions, ListenOptions, OverridableValue, OverridesConfig, PropertyOptions };
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { kebabCase, pascalCase } from 'change-case';
2
- import { API_HOST, STATIC_TAG, API_STACKS, API_REQUEST, API_CONNECTED, LIFECYCLE_UPDATE, STATIC_STYLE, API_STYLE, LIFECYCLE_UPDATED, API_RENDER_COMPLETED, METHOD_RENDER, TYPE_BOOLEAN, TYPE_NUMBER, TYPE_NULL, TYPE_DATE, TYPE_ARRAY, TYPE_OBJECT, TYPE_UNDEFINED, TYPE_STRING, KEY, LIFECYCLE_CONNECTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_ADOPTED, LIFECYCLE_READY } from './constants.js';
2
+ import { API_HOST, STATIC_TAG, API_STACKS, API_REQUEST, API_CONNECTED, LIFECYCLE_UPDATE, STATIC_STYLE, API_STYLE, LIFECYCLE_UPDATED, API_RENDER_COMPLETED, METHOD_RENDER, TYPE_BOOLEAN, TYPE_NUMBER, TYPE_NULL, TYPE_DATE, TYPE_ARRAY, TYPE_OBJECT, TYPE_UNDEFINED, TYPE_STRING, KEY, LIFECYCLE_CONNECTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_ADOPTED, LIFECYCLE_READY, API_DEFAULTS } from './constants.js';
3
3
 
4
4
  /**
5
5
  * Indicates the host of the element.
@@ -267,6 +267,10 @@ const isCSSColor = (input) => {
267
267
  return option.style.color !== '';
268
268
  };
269
269
 
270
+ const isCSSUnit = (input) => {
271
+ return /^\d+(\.\d+)?(px|pt|cm|mm|in|em|rem|%|vw|vh)$/.test(input);
272
+ };
273
+
270
274
  /**
271
275
  * Indicates whether the direction of the element is `Right-To-Left` or not.
272
276
  */
@@ -1215,22 +1219,6 @@ const styles$1 = (input) => {
1215
1219
  .join('; ');
1216
1220
  };
1217
1221
 
1218
- const toCSSColor = (input) => {
1219
- return isCSSColor(input) ? input : undefined;
1220
- };
1221
-
1222
- const toCSSUnit = (input) => {
1223
- if (input === undefined || input === null || input === '') {
1224
- return;
1225
- }
1226
- if (typeof input === 'number' || (typeof input === 'string' && !Number.isNaN(Number(input)))) {
1227
- return `${input}px`;
1228
- }
1229
- if (/^\d+(\.\d+)?(px|pt|cm|mm|in|em|rem|%|vw|vh)$/.test(input)) {
1230
- return input;
1231
- }
1232
- };
1233
-
1234
1222
  function toDecorator(util, ...args) {
1235
1223
  return (target, key) => {
1236
1224
  defineProperty(target, key, {
@@ -1810,15 +1798,20 @@ function Overrides() {
1810
1798
  const overrideKeys = Object.keys(overrides);
1811
1799
  const containerKeys = overrideKeys.filter((breakpoint) => breakpoint in containers);
1812
1800
  const mediaKeys = overrideKeys.filter((breakpoint) => breakpoint in medias);
1813
- let timeout = -1;
1814
1801
  let next = {};
1815
- const apply = (key) => {
1816
- clearTimeout(timeout);
1817
- Object.assign(next, overrides[key]);
1818
- timeout = window.setTimeout(() => {
1819
- Object.assign(host(this), overrides[key]);
1802
+ let scheduled = false;
1803
+ const apply = (overrideKey) => {
1804
+ overrideKey && Object.assign(next, overrides[overrideKey]);
1805
+ if (scheduled)
1806
+ return;
1807
+ scheduled = true;
1808
+ queueMicrotask(() => {
1809
+ scheduled = false;
1810
+ const defaults = Object.assign({}, this[API_DEFAULTS], next);
1811
+ delete defaults[key];
1812
+ Object.assign(host(this), defaults);
1820
1813
  next = {};
1821
- }, 0);
1814
+ });
1822
1815
  };
1823
1816
  for (const overrideKey of overrideKeys) {
1824
1817
  if (activeKeys.delete(overrideKey))
@@ -1838,6 +1831,7 @@ function Overrides() {
1838
1831
  apply(containerKey);
1839
1832
  }
1840
1833
  }
1834
+ apply();
1841
1835
  };
1842
1836
  containerQueryList.addEventListener('change', change);
1843
1837
  const disposer = () => {
@@ -1860,6 +1854,7 @@ function Overrides() {
1860
1854
  apply(mediaKey);
1861
1855
  }
1862
1856
  }
1857
+ apply();
1863
1858
  };
1864
1859
  mediaQueryList.addEventListener('change', change);
1865
1860
  const disposer = () => {
@@ -1967,6 +1962,11 @@ function Property(options) {
1967
1962
  }
1968
1963
  }
1969
1964
  });
1965
+ // TODO
1966
+ wrapMethod('before', target, LIFECYCLE_CONNECTED, function () {
1967
+ this[API_DEFAULTS] ||= {};
1968
+ this[API_DEFAULTS][key] = this[key];
1969
+ });
1970
1970
  // Attach getter and setter to the host element on construction
1971
1971
  wrapMethod('before', target, LIFECYCLE_CONSTRUCTED, function () {
1972
1972
  const get = () => {
@@ -2131,6 +2131,23 @@ const toCssString = (input, parent) => {
2131
2131
  return parent ? result : `:host {${result}}`;
2132
2132
  };
2133
2133
 
2134
+ function Variant() {
2135
+ return (target, key) => {
2136
+ wrapMethod('after', target, LIFECYCLE_UPDATE, function (states) {
2137
+ if (!states.has(key))
2138
+ return;
2139
+ const namespace = getNamespace(target) || '';
2140
+ const tag = getTag(this) || '';
2141
+ const properties = getConfig(namespace).elements?.[tag]?.variants?.[this[key]]?.properties;
2142
+ if (!properties)
2143
+ return;
2144
+ const defaults = Object.assign({}, this[API_DEFAULTS], properties);
2145
+ delete defaults[key];
2146
+ Object.assign(this, defaults);
2147
+ });
2148
+ };
2149
+ }
2150
+
2134
2151
  /**
2135
2152
  * Monitors `@Property` and `@State` to detect changes.
2136
2153
  * The decorated method will be called after any changes,
@@ -2165,4 +2182,4 @@ const attributes = attributes$2;
2165
2182
  const html = html$1;
2166
2183
  const styles = styles$1;
2167
2184
 
2168
- export { Bind, Consumer, Debounce, Direction, Element, Event, Host, IsRTL, Listen, Method, Overrides, Property, Provider, Query, QueryAll, Slots, State, Style, Watch, attributes as a, classes, direction, dispatch, getConfig, getConfigCreator, html as h, host, isCSSColor, isRTL, off, on, query, queryAll, styles as s, setConfig, setConfigCreator, slots, toCSSColor, toCSSUnit, toUnit };
2185
+ export { Bind, Consumer, Debounce, Direction, Element, Event, Host, IsRTL, Listen, Method, Overrides, Property, Provider, Query, QueryAll, Slots, State, Style, Variant, Watch, attributes as a, classes, direction, dispatch, getConfig, getConfigCreator, html as h, host, isCSSColor, isCSSUnit, isRTL, off, on, query, queryAll, styles as s, setConfig, setConfigCreator, slots, toUnit };
@@ -1,6 +1,7 @@
1
1
  declare const KEY = "htmlplus";
2
2
  declare const PACKAGE_NAME = "@htmlplus/element";
3
3
  declare const API_CONNECTED: unique symbol;
4
+ declare const API_DEFAULTS: unique symbol;
4
5
  declare const API_HOST: unique symbol;
5
6
  declare const API_REQUEST: unique symbol;
6
7
  declare const API_RENDER_COMPLETED: unique symbol;
@@ -45,4 +46,4 @@ declare const UTILS_STYLES_IMPORTED = "styles";
45
46
  declare const UTILS_STYLES_LOCAL = "UTILS_STYLES";
46
47
  declare const UTILS_PATH = "@htmlplus/element/internal.js";
47
48
 
48
- export { API_CONNECTED, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
49
+ export { API_CONNECTED, API_DEFAULTS, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
package/dist/constants.js CHANGED
@@ -2,6 +2,7 @@ const KEY = 'htmlplus';
2
2
  const PACKAGE_NAME = '@htmlplus/element';
3
3
  // APIs
4
4
  const API_CONNECTED = Symbol();
5
+ const API_DEFAULTS = Symbol();
5
6
  const API_HOST = Symbol();
6
7
  const API_REQUEST = Symbol();
7
8
  const API_RENDER_COMPLETED = Symbol();
@@ -56,4 +57,4 @@ const UTILS_STYLES_IMPORTED = 'styles';
56
57
  const UTILS_STYLES_LOCAL = 'UTILS_STYLES';
57
58
  const UTILS_PATH = '@htmlplus/element/internal.js';
58
59
 
59
- export { API_CONNECTED, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
60
+ export { API_CONNECTED, API_DEFAULTS, API_HOST, API_RENDER_COMPLETED, API_REQUEST, API_STACKS, API_STYLE, COMMENT_AUTO_ADDED, DECORATOR_CSS_VARIABLE, DECORATOR_ELEMENT, DECORATOR_EVENT, DECORATOR_METHOD, DECORATOR_PROPERTY, DECORATOR_PROPERTY_TYPE, DECORATOR_STATE, ELEMENT_HOST_NAME, KEY, LIFECYCLE_ADOPTED, LIFECYCLE_CONNECTED, LIFECYCLE_CONSTRUCTED, LIFECYCLE_DISCONNECTED, LIFECYCLE_READY, LIFECYCLE_UPDATE, LIFECYCLE_UPDATED, METHOD_RENDER, PACKAGE_NAME, STATIC_STYLE, STATIC_TAG, STYLE_IMPORTED, TYPE_ARRAY, TYPE_BIGINT, TYPE_BOOLEAN, TYPE_DATE, TYPE_ENUM, TYPE_FUNCTION, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TYPE_UNDEFINED, UTILS_ATTRIBUTES_IMPORTED, UTILS_ATTRIBUTES_LOCAL, UTILS_HTML_IMPORTED, UTILS_HTML_LOCAL, UTILS_PATH, UTILS_STYLES_IMPORTED, UTILS_STYLES_LOCAL };
@@ -754,8 +754,10 @@ const customElement = (userOptions) => {
754
754
  preserveComments: true
755
755
  });
756
756
  path.node.body.push(...ast);
757
- },
758
- // TODO
757
+ }
758
+ });
759
+ // TODO
760
+ visitor(ast, {
759
761
  TSTypeReference(path) {
760
762
  if (!t.isIdentifier(path.node.typeName))
761
763
  return;
@@ -779,6 +781,37 @@ const customElement = (userOptions) => {
779
781
  path.skip();
780
782
  }
781
783
  });
784
+ // TODO
785
+ visitor(ast, {
786
+ TSTypeReference(path) {
787
+ if (!t.isIdentifier(path.node.typeName))
788
+ return;
789
+ if (path.node.typeName.name !== 'OverridableValue')
790
+ return;
791
+ const property = path.findParent((p) => p.isTSPropertySignature());
792
+ if (!property)
793
+ return;
794
+ if (!t.isTSPropertySignature(property.node))
795
+ return;
796
+ // biome-ignore lint: TODO
797
+ const name = property.node.key.name || property.node.key.extra.rawValue;
798
+ if (!name)
799
+ return;
800
+ if (!path.node.typeParameters?.params)
801
+ return;
802
+ if (path.node.typeParameters.params.length > 1)
803
+ return;
804
+ const interfaceName = pascalCase(`${context.className}-${name}-Overrides`);
805
+ path.node.typeParameters.params[1] = t.identifier(interfaceName);
806
+ path.skip();
807
+ const has = ast.program.body.some((child) => t.isExportNamedDeclaration(child) &&
808
+ t.isInterfaceDeclaration(child.declaration) &&
809
+ child.declaration.id.name === interfaceName);
810
+ if (has)
811
+ return;
812
+ ast.program.body.push(t.exportNamedDeclaration(t.interfaceDeclaration(t.identifier(interfaceName), undefined, undefined, t.objectTypeAnnotation([]))));
813
+ }
814
+ });
782
815
  }
783
816
  context.script = print(ast);
784
817
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlplus/element",
3
- "version": "3.3.1",
3
+ "version": "3.4.1",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "author": "Masood Abdolian <m.abdolian@gmail.com>",