rip-lang 3.17.4 → 3.17.5

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/src/dts.js CHANGED
@@ -12,7 +12,7 @@ import { emitTsParam, ripToTs } from "./params.js";
12
12
  // emitTypes(tokens, sexpr, source) — generates .d.ts from annotated
13
13
  // tokens and the parsed s-expression tree.
14
14
  //
15
- // INTRINSIC_TYPE_DECLS / INTRINSIC_FN_DECL / ARIA_TYPE_DECLS /
15
+ // INTRINSIC_TYPE_DECLS / INTRINSIC_FN_DECL /
16
16
  // SIGNAL_*, COMPUTED_*, EFFECT_* — declaration tables consumed by
17
17
  // emitTypes() and by typecheck.js when building the virtual TS
18
18
  // file. Browser code never references these.
@@ -44,30 +44,20 @@ export const INTRINSIC_TYPE_DECLS = [
44
44
  // out, which would wrongly drop every SVG attribute. So — like JSX/React — we
45
45
  // hand-author the attribute surface as string | number and add it for SVG tags.
46
46
  "type __RipSvgAttrs = { cx?: string | number; cy?: string | number; r?: string | number; rx?: string | number; ry?: string | number; x?: string | number; y?: string | number; x1?: string | number; y1?: string | number; x2?: string | number; y2?: string | number; dx?: string | number; dy?: string | number; width?: string | number; height?: string | number; d?: string; points?: string; pathLength?: string | number; viewBox?: string; preserveAspectRatio?: string; transform?: string; 'transform-origin'?: string; fill?: string; 'fill-opacity'?: string | number; 'fill-rule'?: string; stroke?: string; 'stroke-width'?: string | number; 'stroke-linecap'?: string; 'stroke-linejoin'?: string; 'stroke-dasharray'?: string | number; 'stroke-dashoffset'?: string | number; 'stroke-opacity'?: string | number; 'stroke-miterlimit'?: string | number; opacity?: string | number; color?: string; 'clip-path'?: string; 'clip-rule'?: string; mask?: string; filter?: string; 'text-anchor'?: string; 'dominant-baseline'?: string; 'alignment-baseline'?: string; 'font-family'?: string; 'font-size'?: string | number; 'font-weight'?: string | number; 'font-style'?: string; 'letter-spacing'?: string | number; 'word-spacing'?: string | number; 'text-decoration'?: string; 'marker-start'?: string; 'marker-mid'?: string; 'marker-end'?: string; offset?: string | number; 'stop-color'?: string; 'stop-opacity'?: string | number; gradientUnits?: string; gradientTransform?: string; spreadMethod?: string; fx?: string | number; fy?: string | number; fr?: string | number; display?: string; visibility?: string; overflow?: string; 'pointer-events'?: string; cursor?: string; 'vector-effect'?: string; 'shape-rendering'?: string; 'color-interpolation-filters'?: string; href?: string; 'xlink:href'?: string };",
47
- "type __RipProps<K extends __RipTag> = { [P in __RipAttrKeys<__RipElementMap[K]>]?: __RipElementMap[K][P] } & __RipEvents<K> & { ref?: string; class?: __RipClassValue | __RipClassValue[]; style?: string; [k: `data-${string}`]: any; [k: `aria-${string}`]: any };",
47
+ "type __RipProps<K extends __RipTag> = { [P in __RipAttrKeys<__RipElementMap[K]>]?: __RipElementMap[K][P] } & __RipEvents<K> & { class?: __RipClassValue | __RipClassValue[]; style?: string; [k: `data-${string}`]: any; [k: `aria-${string}`]: any };",
48
+ // Template-ref validator. `ref:` binds a DOM element into a writable state
49
+ // cell. __RipRefCell<V, K> resolves to `unknown` (an identity intersection)
50
+ // only when V — the cell's full value type — both accepts the tag's element
51
+ // type AND admits null; otherwise it resolves to `never`, collapsing the
52
+ // parameter to `never` so the cell argument fails to assign. The cell shape
53
+ // is written inline (`{ value: V; read(): V }`) rather than `Signal<V>` so
54
+ // the decl is self-contained (no dependency on the Signal interface being in
55
+ // scope) and so a computed (`readonly value`) or a readonly plain field is
56
+ // rejected structurally.
57
+ "type __RipRefCell<V, K extends __RipTag> = [__RipElementMap[K]] extends [NonNullable<V>] ? (null extends V ? unknown : never) : never;",
48
58
  ];
49
59
 
50
- export const INTRINSIC_FN_DECL = 'declare function __ripEl<K extends __RipTag>(tag: K, props?: __RipProps<K>): void;\ndeclare function __ripSvgEl<K extends keyof Omit<SVGElementTagNameMap, keyof HTMLElementTagNameMap>>(tag: K, props?: __RipProps<K> & __RipSvgAttrs): void;\ndeclare function __ripRoute<const T extends string>(s: T): T;';
51
-
52
- export const ARIA_TYPE_DECLS = [
53
- 'type __RipAriaNavHandlers = { next?: () => void; prev?: () => void; first?: () => void; last?: () => void; select?: () => void; dismiss?: () => void; tab?: () => void; char?: () => void; };',
54
- "declare const ARIA: {",
55
- " bindPopover(open: boolean, popover: () => Element | null | undefined, setOpen: (isOpen: boolean) => void, source?: (() => Element | null | undefined) | null): void;",
56
- " bindDialog(open: boolean, dialog: () => Element | null | undefined, setOpen: (isOpen: boolean) => void, dismissable?: boolean): void;",
57
- " popupDismiss(open: boolean, popup: () => Element | null | undefined, close: () => void, els?: Array<() => Element | null | undefined>, repos?: (() => void) | null): void;",
58
- " popupGuard(delay?: number): any;",
59
- " listNav(event: KeyboardEvent, handlers: __RipAriaNavHandlers): void;",
60
- " rovingNav(event: KeyboardEvent, handlers: __RipAriaNavHandlers, orientation?: 'vertical' | 'horizontal' | 'both'): void;",
61
- " positionBelow(trigger: Element | null | undefined, popup: Element | null | undefined, gap?: number, setVisible?: boolean): void;",
62
- " position(trigger: Element | null | undefined, floating: Element | null | undefined, opts?: any): void;",
63
- " trapFocus(panel: Element | null | undefined): void;",
64
- " wireAria(panel: Element, id: string): void;",
65
- " lockScroll(instance: any): void;",
66
- " unlockScroll(instance: any): void;",
67
- " hasAnchor: boolean;",
68
- " [key: string]: any;",
69
- "};",
70
- ];
60
+ export const INTRINSIC_FN_DECL = 'declare function __ripEl<K extends __RipTag>(tag: K, props?: __RipProps<K>): void;\ndeclare function __ripSvgEl<K extends keyof Omit<SVGElementTagNameMap, keyof HTMLElementTagNameMap>>(tag: K, props?: __RipProps<K> & __RipSvgAttrs): void;\ndeclare function __ripRoute<const T extends string>(s: T): T;\ndeclare function __ripRef<K extends __RipTag, V>(tag: K, cell: { value: V; read(): V } & __RipRefCell<V, K>): void;';
71
61
 
72
62
  export const SIGNAL_INTERFACE = 'interface Signal<T> { value: T; read(): T; lock(): Signal<T>; free(): Signal<T>; kill(): T; }';
73
63
  export const SIGNAL_FN = 'declare function __state<T>(value: T | Signal<T>): Signal<T>;';
@@ -910,9 +900,6 @@ export function emitTypes(tokens, sexpr = null, source = '', schemaBehavior = nu
910
900
  if (usesRipIntrinsicProps) {
911
901
  preamble.push(...INTRINSIC_TYPE_DECLS);
912
902
  }
913
- if (/\bARIA\./.test(source)) {
914
- preamble.push(...ARIA_TYPE_DECLS);
915
- }
916
903
  if (usesSignal) {
917
904
  preamble.push(SIGNAL_INTERFACE);
918
905
  if (!explicitlyBound.has('__state')) preamble.push(SIGNAL_FN);
@@ -1052,9 +1039,16 @@ function emitComponentTypes(sexpr, lines, indent, indentLevel, componentVars, so
1052
1039
  optional = isProp ? !!target[2]?.optional : !!target?.optional;
1053
1040
  if (!isProp) {
1054
1041
  componentVars.add(propName);
1055
- let wrapper = (mHead === 'computed') ? 'Computed' : 'Signal';
1056
1042
  let typeStr = type ? tsType(type) : (inferLiteralType(member[2]) || 'any');
1057
- bodyMembers.push(` ${propName}: ${wrapper}<${typeStr}>;`);
1043
+ if (mHead === 'readonly') {
1044
+ // `=!` member: a genuine const plain field — surface as `readonly`,
1045
+ // NOT Signal-wrapped (the runtime emits `this.name = value`, not a
1046
+ // signal). `readonly` makes a consumer reassignment TS2540.
1047
+ bodyMembers.push(` readonly ${propName}: ${typeStr};`);
1048
+ } else {
1049
+ let wrapper = (mHead === 'computed') ? 'Computed' : 'Signal';
1050
+ bodyMembers.push(` ${propName}: ${wrapper}<${typeStr}>;`);
1051
+ }
1058
1052
  continue;
1059
1053
  }
1060
1054
  } else if (mHead === '.') {
@@ -1118,6 +1112,10 @@ function emitComponentTypes(sexpr, lines, indent, indentLevel, componentVars, so
1118
1112
  publicProps.push(` ${propName}${opt}: ${typeStr};`);
1119
1113
  if (mHead === 'state') {
1120
1114
  publicProps.push(` __bind_${propName}__?: Signal<${typeStr}>;`);
1115
+ } else if (mHead === 'readonly') {
1116
+ // Public `=!` prop: also surface the instance member as `readonly` so a
1117
+ // consumer reading `instance.name` sees its const-ness (TS2540 on write).
1118
+ bodyMembers.push(` readonly ${propName}: ${typeStr};`);
1121
1119
  }
1122
1120
  }
1123
1121
 
@@ -1,5 +1,5 @@
1
1
  // Generated from TypeScript's lib.dom.d.ts
2
- // Source: /Users/shreeve/Data/Code/rip-lang/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts
2
+ // Source: /Users/shreeve/Data/Code/rip-lang/node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.dom.d.ts
3
3
  // Run: bun scripts/gen-dom.js
4
4
 
5
5
  export const DOM_EVENT_NAMES = [
@@ -19,6 +19,7 @@ export const DOM_EVENT_NAMES = [
19
19
  'change',
20
20
  'click',
21
21
  'close',
22
+ 'command',
22
23
  'compositionend',
23
24
  'compositionstart',
24
25
  'compositionupdate',
@@ -1,5 +1,5 @@
1
1
  // Generated from TypeScript's lib.dom.d.ts
2
- // Source: /Users/shreeve/Data/Code/rip-lang/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts
2
+ // Source: /Users/shreeve/Data/Code/rip-lang/node_modules/.bun/typescript@6.0.3/node_modules/typescript/lib/lib.dom.d.ts
3
3
  // Run: bun scripts/gen-dom.js
4
4
 
5
5
  export const HTML_TAG_NAMES = [
@@ -184,6 +184,7 @@ export const SVG_TAG_NAMES = [
184
184
  ];
185
185
 
186
186
  export const MATHML_TAG_NAMES = [
187
+ 'a',
187
188
  'annotation',
188
189
  'annotation-xml',
189
190
  'maction',
@@ -973,6 +973,13 @@ grammar =
973
973
  o '- Expression' , '["-", 2]', prec: 'UNARY_MATH'
974
974
  o '+ Expression' , '["+", 2]', prec: 'UNARY_MATH'
975
975
 
976
+ # Postfix `expr as Type` cast. The type rewriter has already collapsed the
977
+ # `as Type` run into a single CAST marker token whose value is the opaque
978
+ # type string — the grammar never parses a type. Left-associative (chains
979
+ # `x as A as B` nest left-to-right) and looser than arithmetic/member/call
980
+ # but tighter than relational/comparison, matching TS `as` precedence.
981
+ o 'Expression CAST' , '["cast", 1, 2]'
982
+
976
983
  # Postfix existence check: expr? → (expr != null)
977
984
  o 'Value ?' , '["?", 1]'
978
985
 
@@ -1046,6 +1053,7 @@ operators = """
1046
1053
  left MATH
1047
1054
  left + -
1048
1055
  left SHIFT
1056
+ left CAST
1049
1057
  left RELATION
1050
1058
  left COMPARE
1051
1059
  left &