@levino/shipyard-base 0.7.5 → 0.7.6-rc-20260316212851

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.
@@ -49,22 +49,50 @@ const { brand, navigation, showBrand = false } = Astro.props as Props
49
49
  <ul class="menu menu-horizontal px-1">
50
50
  {
51
51
  Object.entries(navigation).map(([key, entry]) =>
52
- entry.subEntry ? (
52
+ entry.html ? (
53
+ <li>
54
+ <Fragment set:html={entry.html} />
55
+ </li>
56
+ ) : entry.subEntry ? (
53
57
  <li>
54
58
  <details>
55
- <summary>{entry.label ?? key}</summary>
59
+ <summary>
60
+ {entry.labelHtml ? (
61
+ <Fragment set:html={entry.labelHtml} />
62
+ ) : (
63
+ entry.label ?? key
64
+ )}
65
+ </summary>
56
66
  <ul class="rounded-t-none bg-base-100 p-2">
57
- {Object.entries(entry.subEntry).map(([key, entry]) => (
58
- <li>
59
- <a href={entry.href}>{entry.label ?? key}</a>
60
- </li>
61
- ))}
67
+ {Object.entries(entry.subEntry).map(([subKey, subEntry]) =>
68
+ subEntry.html ? (
69
+ <li>
70
+ <Fragment set:html={subEntry.html} />
71
+ </li>
72
+ ) : (
73
+ <li>
74
+ <a href={subEntry.href}>
75
+ {subEntry.labelHtml ? (
76
+ <Fragment set:html={subEntry.labelHtml} />
77
+ ) : (
78
+ subEntry.label ?? subKey
79
+ )}
80
+ </a>
81
+ </li>
82
+ )
83
+ )}
62
84
  </ul>
63
85
  </details>
64
86
  </li>
65
87
  ) : (
66
88
  <li>
67
- <a href={entry.href}>{entry.label ?? key}</a>
89
+ <a href={entry.href}>
90
+ {entry.labelHtml ? (
91
+ <Fragment set:html={entry.labelHtml} />
92
+ ) : (
93
+ entry.label ?? key
94
+ )}
95
+ </a>
68
96
  </li>
69
97
  ),
70
98
  )
@@ -48,7 +48,11 @@ const isActiveOrHasActiveChild = (entryValue: Entry[string]): boolean => {
48
48
  </span>
49
49
  );
50
50
 
51
- return (
51
+ return entryValue.html ? (
52
+ <li class={entryValue.className}>
53
+ <Fragment set:html={entryValue.html} />
54
+ </li>
55
+ ) : (
52
56
  <li class={entryValue.className}>
53
57
  {hasChildren && isCollapsible ? (
54
58
  // Collapsible category with children
@@ -8,6 +8,12 @@ export type Entry = Record<
8
8
  * Useful for custom label components like buttons, icons, or interactive elements.
9
9
  */
10
10
  labelHtml?: string
11
+ /**
12
+ * Custom HTML that replaces the contents of the navigation entry.
13
+ * The `<li>` wrapper is still rendered; this HTML goes inside it.
14
+ * When provided, label, href, labelHtml, and subEntry are ignored.
15
+ */
16
+ html?: string
11
17
  href?: string
12
18
  subEntry?: Entry
13
19
  active?: boolean
@@ -49,7 +49,7 @@ const props = Astro.props.frontmatter || Astro.props
49
49
 
50
50
  const withLocale = (path: string) =>
51
51
  i18n ? `/${Astro.currentLocale}${path}` : path
52
- const applyLocaleAndSetActive: (navigation: NavigationTree) => NavigationTree =
52
+ const applyLocaleAndSetActive: (nav: NavigationTree) => NavigationTree =
53
53
  mapObjIndexed((entry: NavigationEntry) => ({
54
54
  ...entry,
55
55
  ...(entry.href ? { href: withLocale(entry.href) } : {}),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levino/shipyard-base",
3
- "version": "0.7.5",
3
+ "version": "0.7.6-rc-20260316212851",
4
4
  "description": "Core layouts, components, and configuration for shipyard - a composable page builder for Astro",
5
5
  "keywords": [
6
6
  "astro",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@tailwindcss/typography": "^0.5.10",
42
- "astro": "^5.7",
42
+ "astro": "^6.0.0",
43
43
  "daisyui": "^5",
44
44
  "tailwindcss": "^4"
45
45
  },
@@ -61,7 +61,7 @@
61
61
  "tailwindcss": "^4",
62
62
  "typescript": "^5.2.2",
63
63
  "vite": "^7",
64
- "vitest": "^2.1.8"
64
+ "vitest": "^4.1.0"
65
65
  },
66
66
  "dependencies": {
67
67
  "clsx": "^2.1.0",
@@ -8,6 +8,25 @@ export interface NavigationEntry {
8
8
  * When provided, this takes precedence over the label.
9
9
  */
10
10
  labelHtml?: string
11
+ /**
12
+ * Custom HTML that replaces the contents of the navigation entry.
13
+ * The `<li>` wrapper is still rendered by the navigation component;
14
+ * this HTML is placed inside it.
15
+ * Use this for elements that cannot be rendered as simple links,
16
+ * such as forms with POST actions (e.g., logout buttons).
17
+ *
18
+ * When provided, `label`, `href`, `labelHtml`, and `subEntry` are ignored.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * navigation: {
23
+ * logout: {
24
+ * html: '<form method="post" action="/api/logout"><button type="submit" class="btn btn-ghost">Logout</button></form>'
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ html?: string
11
30
  }
12
31
 
13
32
  export type NavigationTree = Record<string, NavigationEntry>