0x-lang 0.1.19 → 0.1.21

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/README.md CHANGED
@@ -435,6 +435,46 @@ layout col .card: # Apply named style
435
435
  Sizes: `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`<br/>
436
436
  Button styles: `primary`, `secondary`, `danger`, `outline`, `ghost`
437
437
 
438
+ ### CSS Classes & Passthrough Props
439
+
440
+ ```python
441
+ layout col class="container mx-auto p-4":
442
+ text "Title" class="text-xl font-bold text-blue-600"
443
+ button "Save" -> save() class="btn btn-primary"
444
+ input name class="form-input" aria-label="Name" data-testid="name-input"
445
+ ```
446
+
447
+ - `class="..."` adds `className` (React) or `class` (Vue/Svelte) to any element
448
+ - Works with Tailwind CSS, Bootstrap, or any CSS framework
449
+ - Unknown props (`data-*`, `aria-*`, `role`, etc.) pass through as HTML attributes
450
+
451
+ ### Raw Block (Framework Escape Hatch)
452
+
453
+ ```python
454
+ raw:
455
+ <CustomComponent onSpecialEvent={handler} />
456
+
457
+ raw { <div dangerouslySetInnerHTML={{__html: content}} /> }
458
+ ```
459
+
460
+ - `raw:` inserts code directly into JSX/template output (NOT the script section)
461
+ - Different from `js:` which goes into the script/hook section
462
+ - Use for third-party components or framework-specific code
463
+
464
+ ### Component Children
465
+
466
+ ```python
467
+ component Dialog(title="Settings"):
468
+ layout col:
469
+ text "Content"
470
+ button "Close" -> close()
471
+
472
+ component Card(item) # Self-closing (no children)
473
+ ```
474
+
475
+ - When a `component` call ends with `:`, indented children are wrapped inside the component
476
+ - Without `:`, renders as a self-closing tag
477
+
438
478
  ### Control flow
439
479
 
440
480
  ```python
@@ -489,6 +529,13 @@ button "Reset" -> count = 0 # Inline
489
529
  input query @keypress=onKeyPress # Keyboard
490
530
  ```
491
531
 
532
+ ### Performance Optimization (React)
533
+
534
+ - `fn` declarations are auto-wrapped in `useCallback` with extracted deps
535
+ - `derived` values use `useMemo` with extracted deps
536
+ - Components with `prop` declarations are auto-wrapped in `React.memo`
537
+ - No manual optimization needed — the compiler handles it automatically
538
+
492
539
  ---
493
540
 
494
541
  ## Programmatic API
@@ -739,7 +786,7 @@ Flags:
739
786
  git clone https://github.com/hankimis/0x-lang.git
740
787
  cd 0x-lang
741
788
  npm install
742
- npm test # 2,600+ lines of tests
789
+ npm test # 1,767 tests across 9 test suites
743
790
  npm run build
744
791
  ```
745
792
 
@@ -1,5 +1,5 @@
1
1
  // 0x → React Code Generator
2
- import { SIZE_MAP, unquote, capitalize, parseGradient, addPx, getPassthroughProps, KNOWN_LAYOUT_PROPS, KNOWN_TEXT_PROPS, KNOWN_BUTTON_PROPS, KNOWN_INPUT_PROPS, KNOWN_IMAGE_PROPS, KNOWN_LINK_PROPS, KNOWN_TOGGLE_PROPS, KNOWN_SELECT_PROPS } from './shared.js';
2
+ import { SIZE_MAP, unquote, capitalize, parseGradient, addPx, getPassthroughProps, typeExprToJs, getFieldDefault, KNOWN_LAYOUT_PROPS, KNOWN_TEXT_PROPS, KNOWN_BUTTON_PROPS, KNOWN_INPUT_PROPS, KNOWN_IMAGE_PROPS, KNOWN_LINK_PROPS, KNOWN_TOGGLE_PROPS, KNOWN_SELECT_PROPS } from './shared.js';
3
3
  import { SourceMapBuilder } from './source-map.js';
4
4
  export function ctx() {
5
5
  return {
@@ -1262,18 +1262,7 @@ function genModelCode(node) {
1262
1262
  lines.push(`}`);
1263
1263
  return lines.join('\n');
1264
1264
  }
1265
- function typeExprToJs(t) {
1266
- switch (t.kind) {
1267
- case 'primitive': {
1268
- const map = { int: 'number', float: 'number', str: 'string', bool: 'boolean', datetime: 'Date', date: 'Date', time: 'string' };
1269
- return map[t.name] || t.name;
1270
- }
1271
- case 'list': return `${typeExprToJs(t.itemType)}[]`;
1272
- case 'named': return t.name;
1273
- case 'nullable': return `${typeExprToJs(t.inner)} | null`;
1274
- default: return 'any';
1275
- }
1276
- }
1265
+ // typeExprToJs is now imported from shared.ts
1277
1266
  function genExprStandalone(expr) {
1278
1267
  const c = ctx();
1279
1268
  return genExpr(expr, c);
@@ -1377,17 +1366,7 @@ function genFormDecl(node, c) {
1377
1366
  }
1378
1367
  return lines.join('\n ');
1379
1368
  }
1380
- function getFieldDefault(t) {
1381
- if (t.kind === 'primitive') {
1382
- if (t.name === 'str')
1383
- return "''";
1384
- if (t.name === 'int' || t.name === 'float')
1385
- return '0';
1386
- if (t.name === 'bool')
1387
- return 'false';
1388
- }
1389
- return "''";
1390
- }
1369
+ // getFieldDefault is now imported from shared.ts
1391
1370
  // ── Phase 1 Advanced: Table ─────────────────────────
1392
1371
  function genTableUI(node, c) {
1393
1372
  const data = node.dataSource;