@alstar/studio 0.0.0-beta.15 → 0.0.0-beta.16

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.
@@ -26,7 +26,7 @@ export default (props: {
26
26
 
27
27
  if (!data) return html`<p>No block</p>`
28
28
 
29
- const entries = Object.entries(structure.children)
29
+ const entries = Object.entries(structure.blocks)
30
30
 
31
31
  const rows = query.blocks({ parent_id: data.id })
32
32
 
@@ -1,6 +1,7 @@
1
1
  import { Field } from './fields/index.ts'
2
2
  import type { BlocksFieldDefStructure, FieldDefStructure } from '../types.ts'
3
3
  import BlockFieldRenderer from './BlockFieldRenderer.ts'
4
+ import { BlockFieldInstance } from '../utils/define.ts'
4
5
 
5
6
  export default (props: {
6
7
  entryId: number
@@ -11,6 +12,10 @@ export default (props: {
11
12
  }) => {
12
13
  const { entryId, parentId, structure, name, id } = props
13
14
 
15
+ if (structure.instanceOf === BlockFieldInstance) {
16
+ return BlockFieldRenderer({ entryId, parentId, name, structure, id })
17
+ }
18
+
14
19
  switch (structure.type) {
15
20
  case 'text': {
16
21
  return Field.Text({ entryId, parentId, name, id, structure })
@@ -28,8 +33,8 @@ export default (props: {
28
33
  return Field.Text({ entryId, parentId, name, structure, id })
29
34
  }
30
35
 
31
- case 'blocks': {
32
- return BlockFieldRenderer({ entryId, parentId, name, structure, id })
36
+ case 'reference': {
37
+ return Field.Reference({ entryId, parentId, name, structure, id })
33
38
  }
34
39
  }
35
40
  }
@@ -41,6 +41,11 @@ export default (props: {
41
41
  }
42
42
  }
43
43
  } catch (error) {
44
- return html`<p>Error rendering "${name}"</p>`
44
+ console.log(error)
45
+
46
+ return html`
47
+ <p>Error rendering "${name}"</p>
48
+ <pre><code>${JSON.stringify(error, null, 2)}</code></pre>
49
+ `
45
50
  }
46
51
  }
@@ -0,0 +1,67 @@
1
+ import { getOrCreateRow } from '../../utils/get-or-create-row.ts'
2
+ import { html } from '../../utils/html.ts'
3
+ import type { FieldDefStructure, ReferenceFieldStructure } from '../../types.ts'
4
+ import { query } from '../../queries/index.ts'
5
+
6
+ export default (props: {
7
+ entryId: number
8
+ parentId: number
9
+ name: string
10
+ id?: number
11
+ structure: ReferenceFieldStructure
12
+ sortOrder?: number
13
+ }) => {
14
+ const { entryId, parentId, name, structure, sortOrder = 0, id } = props
15
+
16
+ const data = getOrCreateRow({
17
+ parentId,
18
+ name,
19
+ field: structure,
20
+ sortOrder,
21
+ id,
22
+ })
23
+
24
+ if (!data) return html`<p>No block</p>`
25
+
26
+ const entries = query.roots({ type: structure.to }, { depth: 1 })
27
+
28
+ return html`
29
+ <form
30
+ data-on-input="@patch('/studio/api/block', {
31
+ contentType: 'form',
32
+ headers: {
33
+ render: ''
34
+ }
35
+ })"
36
+ >
37
+ <hgroup>
38
+ <label for="block-${data.id}">${structure.label}</label>
39
+ ${structure.description &&
40
+ html`
41
+ <p><small>${structure.description}</small></p>
42
+ `}
43
+ </hgroup>
44
+
45
+ <input
46
+ list="entries-${data.id}"
47
+ id="block-${data.id}"
48
+ name="value"
49
+ value="${data.value}"
50
+ />
51
+ <datalist id="entries-${data.id}">
52
+ ${entries.map((entry) => {
53
+ return html`<option value="${entry.fields.slug.value}">
54
+ ${entry.fields.title.value}
55
+ </option>`
56
+ })}
57
+ </datalist>
58
+
59
+ <input type="hidden" name="id" value="${data.id}" />
60
+
61
+ <!-- <input type="hidden" name="type" value="{structure.type}" />
62
+ <input type="hidden" name="entryId" value="{entryId}" />
63
+ <input type="hidden" name="parentId" value="{parentId}" />
64
+ <input type="hidden" name="name" value="{name}" /> -->
65
+ </form>
66
+ `
67
+ }
@@ -1,7 +1,8 @@
1
1
  import Text from './Text.ts'
2
2
  import Markdown from './Markdown.ts'
3
3
  import Slug, { routes as slugRoutes } from './Slug.ts'
4
+ import Reference from './Reference.ts'
4
5
 
5
- export const Field = { Text, Markdown, Slug }
6
+ export const Field = { Text, Markdown, Slug, Reference }
6
7
 
7
8
  export const fieldRoutes = [slugRoutes]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alstar/studio",
3
- "version": "0.0.0-beta.15",
3
+ "version": "0.0.0-beta.16",
4
4
  "type": "module",
5
5
  "main": "index.ts",
6
6
  "bin": {
@@ -13,9 +13,9 @@
13
13
  "@hono/node-server": "^1.18.1",
14
14
  "@starfederation/datastar-sdk": "1.0.0-RC.1",
15
15
  "hono": "^4.8.12",
16
- "@alstar/ui": "0.0.0-beta.2",
16
+ "@alstar/db": "0.0.0-beta.1",
17
17
  "@alstar/refresher": "0.0.0-beta.3",
18
- "@alstar/db": "0.0.0-beta.1"
18
+ "@alstar/ui": "0.0.0-beta.3"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^24.1.0",
@@ -1,4 +1,5 @@
1
1
  @import 'https://esm.sh/@alstar/ui/red.css';
2
+ /* @import '../node_modules/@alstar/ui/slate.css'; */
2
3
  @import './css/admin-panel.css';
3
4
  @import './css/blocks-field.css';
4
5
  @import './css/settings.css';
@@ -7,7 +7,7 @@ function buildForest(blocks: DBBlockResult[]): DBBlockResult[] {
7
7
  const roots: DBBlockResult[] = []
8
8
 
9
9
  for (const block of blocks) {
10
- block.children = []
10
+ block.blocks = []
11
11
  map.set(block.id, block)
12
12
  }
13
13
 
@@ -16,14 +16,14 @@ function buildForest(blocks: DBBlockResult[]): DBBlockResult[] {
16
16
  roots.push(block)
17
17
  } else {
18
18
  const parent = map.get(block.parent_id)
19
- if (parent) parent.children!.push(block)
19
+ if (parent) parent.blocks!.push(block)
20
20
  }
21
21
  }
22
22
 
23
- // Sort children by sort_order recursively
23
+ // Sort blocks by sort_order recursively
24
24
  const sortChildren = (node: DBBlockResult) => {
25
- node.children!.sort((a, b) => a.sort_order - b.sort_order)
26
- node.children!.forEach(sortChildren)
25
+ node.blocks!.sort((a, b) => a.sort_order - b.sort_order)
26
+ node.blocks!.forEach(sortChildren)
27
27
  }
28
28
  roots.forEach(sortChildren)
29
29
 
@@ -35,7 +35,7 @@ function buildTree(blocks: DBBlockResult[]): DBBlockResult {
35
35
  const roots: DBBlockResult[] = []
36
36
 
37
37
  for (const block of blocks) {
38
- block.children = []
38
+ block.blocks = []
39
39
  map.set(block.id, block)
40
40
  }
41
41
 
@@ -44,14 +44,14 @@ function buildTree(blocks: DBBlockResult[]): DBBlockResult {
44
44
  roots.push(block)
45
45
  } else {
46
46
  const parent = map.get(block.parent_id)
47
- if (parent) parent.children!.push(block)
47
+ if (parent) parent.blocks!.push(block)
48
48
  }
49
49
  }
50
50
 
51
- // Sort children by sort_order recursively
51
+ // Sort blocks by sort_order recursively
52
52
  const sortChildren = (node: DBBlockResult) => {
53
- node.children!.sort((a, b) => a.sort_order - b.sort_order)
54
- node.children!.forEach(sortChildren)
53
+ node.blocks!.sort((a, b) => a.sort_order - b.sort_order)
54
+ node.blocks!.forEach(sortChildren)
55
55
  }
56
56
  roots.forEach(sortChildren)
57
57
 
@@ -65,7 +65,7 @@ function transformBlocksTree(
65
65
  const fields: Record<string, DBBlockResult> = {}
66
66
  let hasFields = false
67
67
 
68
- for (const child of block.children ?? []) {
68
+ for (const child of block.blocks ?? []) {
69
69
  const transformedChild = transformBlocksTree(
70
70
  child,
71
71
  child.type === 'blocks',
@@ -82,7 +82,7 @@ function transformBlocksTree(
82
82
  }
83
83
 
84
84
  if (!isBlocksChild) {
85
- delete block.children
85
+ delete block.blocks
86
86
  } else {
87
87
  delete block.fields
88
88
  }
@@ -265,7 +265,7 @@ function buildTree2(items: DBRow[]): TODO | null {
265
265
 
266
266
  let root: TODO | null = null;
267
267
 
268
- // Second pass: assign children to parents
268
+ // Second pass: assign blocks to parents
269
269
  for (const item of map.values()) {
270
270
  if (item.parent_id === null) {
271
271
  root = item; // Root node
@@ -273,8 +273,8 @@ function buildTree2(items: DBRow[]): TODO | null {
273
273
  const parent = map.get(item.parent_id);
274
274
  if (parent) {
275
275
  if(parent.type === 'blocks') {
276
- if (!parent.children) parent.children = [];
277
- parent.children.push(item);
276
+ if (!parent.blocks) parent.blocks = [];
277
+ parent.blocks.push(item);
278
278
  } else {
279
279
  if (!parent.fields) parent.fields = {};
280
280
  parent.fields[item.name] = item;
package/schemas.ts CHANGED
@@ -16,7 +16,7 @@ export const blocksTable = {
16
16
  columns: sql`
17
17
  name TEXT not null,
18
18
  label TEXT not null,
19
- type TEXT not null,
19
+ type TEXT,
20
20
  value TEXT,
21
21
  options JSON,
22
22
  status TEXT default 'enabled',
package/types.ts CHANGED
@@ -21,14 +21,13 @@ export type DeepReadonly<T> =
21
21
  export type PrimitiveField = {
22
22
  name: string
23
23
  label: string
24
- type: 'text' | 'slug' | 'markdown' | 'image'
24
+ type: 'text' | 'slug' | 'markdown' | 'image' | 'reference'
25
25
  }
26
26
 
27
27
  export type BlockField = {
28
28
  name: string
29
29
  label: string
30
- type: 'blocks'
31
- children: Record<string, Field | Block>
30
+ blocks: Record<string, Field | Block>
32
31
  }
33
32
 
34
33
  export type Field = PrimitiveField | BlockField
@@ -44,7 +43,7 @@ export type Structure = Record<string, BlockDefStructure>
44
43
  // export type Structure = Record<string, BlockDefStructure>
45
44
 
46
45
  // --- Field & block definitions ---
47
- type FieldType = 'text' | 'slug' | 'markdown' | 'image'
46
+ type FieldType = 'text' | 'slug' | 'markdown' | 'image' | 'reference'
48
47
 
49
48
  interface BaseField {
50
49
  label: string
@@ -68,19 +67,27 @@ interface ImageFieldStructure extends ImageField {
68
67
  instanceOf: typeof FieldInstance
69
68
  }
70
69
 
70
+ interface ReferenceField extends BaseField {
71
+ type: 'reference'
72
+ to: string | string[]
73
+ }
74
+
75
+ export interface ReferenceFieldStructure extends ReferenceField {
76
+ instanceOf: typeof FieldInstance
77
+ }
78
+
71
79
  export interface BlocksFieldDef {
72
80
  label: string
73
- type: 'blocks'
74
81
  description?: string
75
- children: Record<string, BlockDefStructure | FieldDefStructure>
82
+ blocks: Record<string, BlockDefStructure | FieldDefStructure>
76
83
  }
77
84
 
78
85
  export interface BlocksFieldDefStructure extends BlocksFieldDef {
79
86
  instanceOf: typeof BlockFieldInstance
80
87
  }
81
88
 
82
- export type FieldDef = TextField | ImageField
83
- export type FieldDefStructure = TextFieldStructure | ImageFieldStructure
89
+ export type FieldDef = TextField | ImageField | ReferenceField
90
+ export type FieldDefStructure = TextFieldStructure | ImageFieldStructure | ReferenceFieldStructure
84
91
 
85
92
  export interface BlockDef {
86
93
  label: string
@@ -127,8 +134,7 @@ export type DBPrimitiveFieldResult = BaseDBResult & {
127
134
  }
128
135
 
129
136
  export type DBBlockFieldResult = BaseDBResult & {
130
- type: 'blocks'
131
- children: DBBlockResult[]
137
+ blocks: DBBlockResult[]
132
138
  }
133
139
 
134
140
  export type DBBlockResult = BaseDBResult & {
@@ -5,6 +5,7 @@ import type {
5
5
  BlocksFieldDefStructure,
6
6
  FieldDefStructure,
7
7
  } from '../types.ts'
8
+ import { BlockFieldInstance } from './define.ts'
8
9
 
9
10
  export function getOrCreateRow(props: {
10
11
  parentId: string | number | null
@@ -32,7 +33,7 @@ export function getOrCreateRow(props: {
32
33
  const change = db.insertInto('blocks', {
33
34
  name: name?.toString(),
34
35
  label: field.label?.toString(),
35
- type: field.type?.toString(),
36
+ type: field.instanceOf === BlockFieldInstance ? 'blocks' : field.type?.toString(),
36
37
  sort_order: sortOrder,
37
38
  parent_id: parentId,
38
39
  })