element-vir 25.0.2 → 25.2.0

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.
@@ -79,7 +79,6 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
79
79
  * be called using the `.assign()` method on an element definition inside of an HTML template.
80
80
  */
81
81
  abstract assignInputs(inputs: EmptyObject extends Required<Inputs> ? never : Partial<Inputs>): void;
82
- abstract _haveInputsBeenSet: boolean;
83
82
  /** The element definition for this element instance. */
84
83
  abstract readonly definition: DeclarativeElementDefinition<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
85
84
  }
@@ -88,7 +87,7 @@ export declare abstract class DeclarativeElement<TagName extends CustomElementTa
88
87
  *
89
88
  * @category Internal
90
89
  */
91
- export type AssignMethod<Inputs extends PropertyInitMapBase> = IsAny<Inputs> extends true ? any : IsEmptyObject<Required<Inputs>> extends true ? (inputsObject: never) => never : (inputsObject: IsEmptyObject<Required<Inputs>> extends true ? never : Inputs) => MinimalDefinitionWithInputs;
90
+ export type AssignMethod<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase> = IsAny<Inputs> extends true ? any : IsEmptyObject<Required<Inputs>> extends true ? (inputsObject: never) => never : (inputsObject: IsEmptyObject<Required<Inputs>> extends true ? never : Inputs) => MinimalDefinitionWithInputs<TagName>;
92
91
  /**
93
92
  * All static properties on a declarative element. These all come from the element's definition.
94
93
  *
@@ -96,7 +95,7 @@ export type AssignMethod<Inputs extends PropertyInitMapBase> = IsAny<Inputs> ext
96
95
  */
97
96
  export type StaticDeclarativeElementProperties<TagName extends CustomElementTagName, Inputs extends PropertyInitMapBase, State extends PropertyInitMapBase, EventsInit extends EventsInitMap, HostClassKeys extends BaseCssPropertyName<TagName>, CssVarKeys extends BaseCssPropertyName<TagName>, SlotNames extends ReadonlyArray<string>> = {
98
97
  /** Assign inputs to an element directly on its interpolated tag. */
99
- readonly assign: AssignMethod<Inputs>;
98
+ readonly assign: AssignMethod<TagName, Inputs>;
100
99
  assignedInputs: Inputs | undefined;
101
100
  /** Pass through the render callback for direct unit testability */
102
101
  readonly render: RenderCallback<TagName, Inputs, State, EventsInit, HostClassKeys, CssVarKeys, SlotNames>;
@@ -109,6 +108,6 @@ export type StaticDeclarativeElementProperties<TagName extends CustomElementTagN
109
108
  readonly UpdateStateType: UpdateStateCallback<State>;
110
109
  readonly hostClasses: HostClassNamesMap<string, HostClassKeys>;
111
110
  readonly cssVars: CssVars<TagName, CssVarKeys>;
112
- readonly tagName: string;
111
+ readonly tagName: TagName;
113
112
  readonly styles: CSSResult;
114
113
  };
@@ -5,7 +5,6 @@ import { defineCssVars } from 'lit-css-vars';
5
5
  import { css } from '../template-transforms/vir-css/vir-css.js';
6
6
  import { DeclarativeElement, } from './declarative-element.js';
7
7
  import { defaultDeclarativeElementDefinitionOptions, } from './definition-options.js';
8
- import { hasDeclarativeElementParent } from './has-declarative-element-parent.js';
9
8
  import { assignInputs } from './properties/assign-inputs.js';
10
9
  import { assertValidCssProperties } from './properties/css-properties.js';
11
10
  import { createEventDescriptorMap, } from './properties/element-events.js';
@@ -108,18 +107,9 @@ export function defineElementNoInputs(init) {
108
107
  _stateCalled = false;
109
108
  _hasRendered = false;
110
109
  _lastRenderedProps = undefined;
111
- _haveInputsBeenSet = false;
112
110
  render() {
113
111
  this._internalRenderCount++;
114
112
  try {
115
- if (
116
- // This ignores elements at the root of a page, as they can't receive inputs from
117
- // other elements (cause they have no custom element ancestors).
118
- hasDeclarativeElementParent(this) &&
119
- !this._haveInputsBeenSet &&
120
- !elementOptions.ignoreUnsetInputs) {
121
- console.warn(this, `${init.tagName} got rendered before its input object was set. This was most likely caused by forgetting to use '.assign()' on its opening tag. If no inputs are intended, use '${defineElementNoInputs.name}' to define ${init.tagName}.`);
122
- }
123
113
  this._hasRendered = true;
124
114
  const renderParams = this.createRenderParams();
125
115
  if (!this._stateCalled && init.state) {
@@ -37,7 +37,6 @@ export function defineElement(
37
37
  return defineElementNoInputs({
38
38
  ...init,
39
39
  options: {
40
- ignoreUnsetInputs: false,
41
40
  ...init.options,
42
41
  },
43
42
  });
@@ -4,8 +4,6 @@
4
4
  * @category Internal
5
5
  */
6
6
  export type DeclarativeElementDefinitionOptions = {
7
- /** For internal use only. */
8
- ignoreUnsetInputs: boolean;
9
7
  /**
10
8
  * If set to true, state property keys will be allowed to change at run time. Turning this on
11
9
  * will greatly reduce type safety and should be avoided.
@@ -4,6 +4,5 @@
4
4
  * @internal
5
5
  */
6
6
  export const defaultDeclarativeElementDefinitionOptions = {
7
- ignoreUnsetInputs: true,
8
7
  allowPolymorphicState: false,
9
8
  };
@@ -1,2 +1 @@
1
1
  export declare function assignInputs(element: Element, inputs: object): void;
2
- export declare function markInputsAsHavingBeenSet(element: Element): void;
@@ -22,10 +22,4 @@ export function assignInputs(element, inputs) {
22
22
  }
23
23
  });
24
24
  }
25
- markInputsAsHavingBeenSet(element);
26
- }
27
- export function markInputsAsHavingBeenSet(element) {
28
- if (!element._haveInputsBeenSet) {
29
- element._haveInputsBeenSet = true;
30
- }
31
25
  }
package/dist/index.d.ts CHANGED
@@ -35,5 +35,6 @@ export * from './template-transforms/vir-css/vir-css.js';
35
35
  export * from './template-transforms/vir-html/html-interpolation.js';
36
36
  export * from './template-transforms/vir-html/vir-html.js';
37
37
  export * from './typed-event/typed-event.js';
38
+ export * from './util/increment.js';
38
39
  export * from './util/lit-template.js';
39
40
  export * from './util/type.js';
package/dist/index.js CHANGED
@@ -35,5 +35,6 @@ export * from './template-transforms/vir-css/vir-css.js';
35
35
  export * from './template-transforms/vir-html/html-interpolation.js';
36
36
  export * from './template-transforms/vir-html/vir-html.js';
37
37
  export * from './typed-event/typed-event.js';
38
+ export * from './util/increment.js';
38
39
  export * from './util/lit-template.js';
39
40
  export * from './util/type.js';
@@ -6,8 +6,8 @@ import { PropertyInitMapBase } from '../declarative-element/properties/element-p
6
6
  *
7
7
  * @category Internal
8
8
  */
9
- export type MinimalElementDefinition = {
10
- tagName: string;
9
+ export type MinimalElementDefinition<TagName extends string = string> = {
10
+ tagName: TagName;
11
11
  elementOptions?: DeclarativeElementDefinitionOptions | undefined;
12
12
  /** This is used when wrapping interpolated raw tag name strings. */
13
13
  tagInterpolationKey?: {
@@ -20,14 +20,14 @@ export type MinimalElementDefinition = {
20
20
  *
21
21
  * @category Internal
22
22
  */
23
- export type MinimalDefinitionWithInputs = {
23
+ export type MinimalDefinitionWithInputs<TagName extends string = string> = {
24
24
  /**
25
25
  * This is what marks instance of this type as such. This does not use a symbol so it's
26
26
  * compatible with multiple `element-vir` versions being installed at once (like if a dependency
27
27
  * uses a different version).
28
28
  */
29
29
  _elementVirIsMinimalDefinitionWithInputs: true;
30
- definition: MinimalElementDefinition;
30
+ definition: MinimalElementDefinition<TagName>;
31
31
  inputs: PropertyInitMapBase;
32
32
  };
33
33
  /**
@@ -1,7 +1,8 @@
1
- import { type AnyFunction } from '@augment-vir/common';
1
+ import { type AnyFunction, type Overwrite } from '@augment-vir/common';
2
2
  import { type CSSResult, type TemplateResult, type nothing } from 'lit';
3
- import { type EmptyObject } from 'type-fest';
3
+ import { type EmptyObject, type HasRequiredKeys, type IsNever } from 'type-fest';
4
4
  import { type DeclarativeElementDefinition } from '../../declarative-element/declarative-element.js';
5
+ import type { Decrement, Increment } from '../../util/increment.js';
5
6
  import { type MinimalDefinitionWithInputs, type MinimalElementDefinition } from '../minimal-element-definition.js';
6
7
  /**
7
8
  * Unfortunately the type for `DirectiveResult` means it's just an empty object. So in order to
@@ -17,3 +18,25 @@ export type DirectiveOutput = EmptyObject;
17
18
  * @category Internal
18
19
  */
19
20
  export type HtmlInterpolation = null | undefined | string | number | boolean | bigint | CSSResult | Readonly<CSSResult> | Element | Readonly<Element> | TemplateResult | Readonly<TemplateResult> | MinimalElementDefinition | Readonly<MinimalElementDefinition> | MinimalDefinitionWithInputs | Readonly<MinimalDefinitionWithInputs> | DeclarativeElementDefinition | Readonly<DeclarativeElementDefinition> | DirectiveOutput | Readonly<DirectiveOutput> | AnyFunction | typeof nothing | HtmlInterpolation[] | ReadonlyArray<HtmlInterpolation>;
21
+ /**
22
+ * This type ensures that interpolated element definitions are not missing their inputs, when inputs
23
+ * are required.
24
+ *
25
+ * @category Internal
26
+ */
27
+ export type VerifyHtmlValues<Values extends HtmlInterpolation[], WaitingForEndTags extends Record<string, number> = {}> = Values extends [
28
+ infer CurrentDefinition extends DeclarativeElementDefinition,
29
+ ...infer Rest extends HtmlInterpolation[]
30
+ ] ? CurrentDefinition extends DeclarativeElementDefinition<infer TagName, infer Inputs> ? HasRequiredKeys<Inputs> extends true ? IsNever<Decrement<WaitingForEndTags[TagName]>> extends true ? [
31
+ `ERROR: This element is missing its inputs.`,
32
+ ...VerifyHtmlValues<Rest, WaitingForEndTags>
33
+ ] : [
34
+ CurrentDefinition,
35
+ ...VerifyHtmlValues<Rest, Overwrite<WaitingForEndTags, Record<TagName, Decrement<WaitingForEndTags[TagName]>>>>
36
+ ] : [CurrentDefinition, ...VerifyHtmlValues<Rest, WaitingForEndTags>] : [CurrentDefinition, ...VerifyHtmlValues<Rest, WaitingForEndTags>] : Values extends [
37
+ infer CurrentDefinition extends MinimalDefinitionWithInputs,
38
+ ...infer Rest extends HtmlInterpolation[]
39
+ ] ? [
40
+ CurrentDefinition,
41
+ ...VerifyHtmlValues<Rest, Overwrite<WaitingForEndTags, Record<CurrentDefinition['definition']['tagName'], Increment<WaitingForEndTags[CurrentDefinition['definition']['tagName']]>>>>
42
+ ] : Values;
@@ -60,12 +60,6 @@ function transformHtml(...[lastNewString, currentTemplateString, rawCurrentValue
60
60
  if (!shouldHaveTagNameHere || !isTagNameWrapper) {
61
61
  return undefined;
62
62
  }
63
- if (isOpeningTag &&
64
- currentValue.elementOptions &&
65
- !currentValue.elementOptions.ignoreUnsetInputs &&
66
- !isMinimalDefinitionWithInputs(rawCurrentValue)) {
67
- throw new Error(`Missing inputs for '${currentValue.tagName}'`);
68
- }
69
63
  const replacement = currentValue.tagName;
70
64
  return {
71
65
  replacement,
@@ -1,5 +1,5 @@
1
1
  import { HTMLTemplateResult } from '../../lit-exports/all-lit-exports.js';
2
- import { HtmlInterpolation } from './html-interpolation.js';
2
+ import { HtmlInterpolation, VerifyHtmlValues } from './html-interpolation.js';
3
3
  /**
4
4
  * Interprets a template literal as an HTML template which is lazily rendered to the DOM.
5
5
  *
@@ -8,4 +8,4 @@ import { HtmlInterpolation } from './html-interpolation.js';
8
8
  *
9
9
  * @category Element Definition
10
10
  */
11
- export declare function html(inputTemplateStrings: TemplateStringsArray, ...inputValues: HtmlInterpolation[]): HTMLTemplateResult;
11
+ export declare function html<const Values extends HtmlInterpolation[]>(inputTemplateStrings: TemplateStringsArray, ...inputValues: VerifyHtmlValues<Values>): HTMLTemplateResult;
@@ -0,0 +1,55 @@
1
+ import type { ArrayElement } from '@augment-vir/common';
2
+ import type { IsNever } from 'type-fest';
3
+ /**
4
+ * The largest number in this tuple is the largest number of nestings of the same element that
5
+ * `element-vir` will support with types (in runtime it'll support any level of nesting the same
6
+ * element).
7
+ *
8
+ * @category Internal
9
+ */
10
+ export type Incrementable = [
11
+ 0,
12
+ 1,
13
+ 2,
14
+ 3,
15
+ 4,
16
+ 5,
17
+ 6,
18
+ 7,
19
+ 8,
20
+ 9,
21
+ 10,
22
+ 11,
23
+ 12,
24
+ 13,
25
+ 14,
26
+ 15,
27
+ 16,
28
+ 17,
29
+ 18,
30
+ 19,
31
+ 20,
32
+ 21,
33
+ 22,
34
+ 23,
35
+ 24,
36
+ 25,
37
+ 26,
38
+ 27,
39
+ 28,
40
+ 29,
41
+ 30
42
+ ];
43
+ /**
44
+ * Increments the given number. If an invalid type parameter is given, it is treated as `0` and this
45
+ * will output `1`. If the upper bound of increments has been reached, this will output `never`.
46
+ *
47
+ * @category Internal
48
+ */
49
+ export type Increment<T> = IsNever<Extract<ArrayElement<Incrementable>, T>> extends true ? IsNever<T> extends true ? 1 : never : Incrementable extends [any, ...infer Rest] ? T extends keyof Rest ? Rest[T] extends undefined ? never : Rest[T] : 1 : 1;
50
+ /**
51
+ * Decrements the given number. If an invalid type parameter is given, `never` is the output.
52
+ *
53
+ * @category Internal
54
+ */
55
+ export type Decrement<T> = IsNever<Extract<ArrayElement<Incrementable>, T>> extends true ? never : T extends keyof Incrementable ? [never, ...Incrementable][T] : never;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "element-vir",
3
- "version": "25.0.2",
3
+ "version": "25.2.0",
4
4
  "keywords": [
5
5
  "custom",
6
6
  "web",
@@ -38,8 +38,8 @@
38
38
  "test:docs": "virmator docs check"
39
39
  },
40
40
  "dependencies": {
41
- "@augment-vir/assert": "^31.10.0",
42
- "@augment-vir/common": "^31.10.0",
41
+ "@augment-vir/assert": "^31.10.1",
42
+ "@augment-vir/common": "^31.10.1",
43
43
  "date-vir": "^7.3.1",
44
44
  "lit": "^3.2.1",
45
45
  "lit-css-vars": "^3.0.11",
@@ -49,8 +49,8 @@
49
49
  "typed-event-target": "^4.0.3"
50
50
  },
51
51
  "devDependencies": {
52
- "@augment-vir/test": "^31.10.0",
53
- "@augment-vir/web": "^31.10.0",
52
+ "@augment-vir/test": "^31.10.1",
53
+ "@augment-vir/web": "^31.10.1",
54
54
  "@web/dev-server-esbuild": "^1.0.4",
55
55
  "@web/test-runner": "^0.20.0",
56
56
  "@web/test-runner-commands": "^0.9.0",
@@ -59,10 +59,10 @@
59
59
  "html-spec-tags": "^2.2.2",
60
60
  "istanbul-smart-text-reporter": "^1.1.5",
61
61
  "markdown-code-example-inserter": "^3.0.3",
62
- "type-fest": "^4.37.0",
63
- "typedoc": "^0.27.9",
62
+ "type-fest": "^4.38.0",
63
+ "typedoc": "^0.28.1",
64
64
  "typescript": "5.8.2",
65
- "vite": "^6.2.1",
65
+ "vite": "^6.2.3",
66
66
  "vite-tsconfig-paths": "^5.1.4"
67
67
  },
68
68
  "engines": {