@evanion/astro-widget 0.1.0 → 0.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 0.2.0 (2026-09-10)
2
+
3
+ ### 🩹 Fixes
4
+
5
+ - ⚠️ **astro-widget:** report validation problems in english ([e51907c](https://github.com/Evanion/libraries/commit/e51907c))
6
+ - ⚠️ **astro-widget:** keep placement data out of block props ([2378269](https://github.com/Evanion/libraries/commit/2378269))
7
+
8
+ ### ⚠️ Breaking Changes
9
+
10
+ - **astro-widget:** report validation problems in english ([e51907c](https://github.com/Evanion/libraries/commit/e51907c))
11
+ BlockProblem.message strings changed. A caller matching on the
12
+ old text must match "unknown block type", "missing field <name>" and "blocks is
13
+ not a list" instead.
14
+ - **astro-widget:** keep placement data out of block props ([2378269](https://github.com/Evanion/libraries/commit/2378269))
15
+ a block that read placement data out of its own props must now
16
+ read it from `meta` on the item chrome instead.
17
+ Part of #71
18
+
19
+ ### ❤️ Thank You
20
+
21
+ - Claude Opus 5 (1M context)
22
+ - Mikael Pettersson @Evanion
23
+
1
24
  ## 0.1.0 (2026-08-30)
2
25
 
3
26
  ### 🚀 Features
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ function t(e, n, r = {}) {
8
8
  if (!Array.isArray(e)) return [{
9
9
  index: -1,
10
10
  type: "-",
11
- message: "sektionslistan är inte en lista"
11
+ message: "blocks is not a list"
12
12
  }];
13
13
  let i = [];
14
14
  return e.forEach((e, a) => {
@@ -16,14 +16,14 @@ function t(e, n, r = {}) {
16
16
  if (!(o in n)) i.push({
17
17
  index: a,
18
18
  type: o,
19
- message: "okänd blocktyp"
19
+ message: "unknown block type"
20
20
  });
21
21
  else for (let t of r[o] ?? []) {
22
22
  let n = e[t];
23
23
  (n == null || typeof n == "string" && n.trim() === "") && i.push({
24
24
  index: a,
25
25
  type: o,
26
- message: `saknar fältet ${t}`
26
+ message: `missing field ${t}`
27
27
  });
28
28
  }
29
29
  Array.isArray(e?.children) && i.push(...t(e.children, n, r));
package/dist/types.d.ts CHANGED
@@ -9,6 +9,10 @@ export interface BlockItem {
9
9
  <slot />, not through a `children` prop. A block that wants nesting
10
10
  renders <Widgets items={children} registry={registry} /> itself. */
11
11
  children?: BlockItem[];
12
+ /** Placement and presentation data for `chrome.item`. Handed to the item
13
+ wrapper and never spread into the block's own props, because where a
14
+ block sits is not something the block should know. */
15
+ meta?: Record<string, unknown>;
12
16
  /** Everything else is passed to the component as props. */
13
17
  [key: string]: unknown;
14
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;2EAGuE;IACvE,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB,2DAA2D;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;2EAGuE;IACvE,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;IACvB;;6DAEyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,2DAA2D;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evanion/astro-widget",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Render CMS-driven Astro sections from structured block data. Build-time, zero runtime.",
5
5
  "keywords": [
6
6
  "astro",
@@ -47,15 +47,17 @@
47
47
  "!src/**/*.test.*",
48
48
  "!src/**/*.spec.*",
49
49
  "!src/**/*.test-d.*",
50
+ "!src/**/__fixtures__/**",
50
51
  "!src/test-setup.ts",
51
52
  "README.md",
52
53
  "LICENSE",
53
54
  "CHANGELOG.md"
54
55
  ],
55
56
  "publishConfig": {
56
- "access": "public"
57
+ "access": "public",
58
+ "provenance": true
57
59
  },
58
60
  "peerDependencies": {
59
- "astro": ">=5"
61
+ "astro": "^7.3.1"
60
62
  }
61
63
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Ambient types for `.astro` imports.
3
+ *
4
+ * Apps get these from `astro sync`, which writes `.astro/types.d.ts` into the
5
+ * project. A library has no Astro project to sync, so the one declaration the
6
+ * tests need is written by hand.
7
+ */
8
+ declare module '*.astro' {
9
+ const Component: import('astro/runtime/server/index.js').AstroComponentFactory;
10
+ export default Component;
11
+ }
@@ -29,10 +29,14 @@ const Item = chrome?.item as never;
29
29
  const Component = registry[item?.type] as never;
30
30
  if (!Component) return null;
31
31
 
32
- const { type, id, children, ...props } = item;
32
+ // `meta` is placement data for the item chrome -- grid column, span,
33
+ // ordering, CMS edit affordances. It is destructured out here so it never
34
+ // reaches the block: where a block sits is not something the block should
35
+ // know, and spreading it in would collide with the block's own props.
36
+ const { type, id, children, meta, ...props } = item;
33
37
 
34
38
  return Item ? (
35
- <Item type={type} id={id} {...props}>
39
+ <Item type={type} id={id} meta={meta} {...props}>
36
40
  <Component {...props} id={id} ctx={ctx} children={children} />
37
41
  </Item>
38
42
  ) : (
package/src/types.ts CHANGED
@@ -9,6 +9,10 @@ export interface BlockItem {
9
9
  <slot />, not through a `children` prop. A block that wants nesting
10
10
  renders <Widgets items={children} registry={registry} /> itself. */
11
11
  children?: BlockItem[];
12
+ /** Placement and presentation data for `chrome.item`. Handed to the item
13
+ wrapper and never spread into the block's own props, because where a
14
+ block sits is not something the block should know. */
15
+ meta?: Record<string, unknown>;
12
16
  /** Everything else is passed to the component as props. */
13
17
  [key: string]: unknown;
14
18
  }
@@ -13,7 +13,7 @@ export function validateBlocks(
13
13
  required: Record<string, string[]> = {}
14
14
  ): BlockProblem[] {
15
15
  if (!Array.isArray(items)) {
16
- return [{ index: -1, type: '-', message: 'sektionslistan är inte en lista' }];
16
+ return [{ index: -1, type: '-', message: 'blocks is not a list' }];
17
17
  }
18
18
 
19
19
  const problems: BlockProblem[] = [];
@@ -22,7 +22,7 @@ export function validateBlocks(
22
22
  const type = typeof item?.type === 'string' ? item.type : '-';
23
23
 
24
24
  if (!(type in registry)) {
25
- problems.push({ index, type, message: 'okänd blocktyp' });
25
+ problems.push({ index, type, message: 'unknown block type' });
26
26
  } else {
27
27
  for (const field of required[type] ?? []) {
28
28
  const value = item[field];
@@ -31,7 +31,7 @@ export function validateBlocks(
31
31
  value === null ||
32
32
  (typeof value === 'string' && value.trim() === '');
33
33
  if (blank) {
34
- problems.push({ index, type, message: `saknar fältet ${field}` });
34
+ problems.push({ index, type, message: `missing field ${field}` });
35
35
  }
36
36
  }
37
37
  }