@edoxen/browser 0.1.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/README.md +45 -0
- package/dist/cli.js +4475 -0
- package/package.json +82 -0
- package/src/astro/components/ActionTypeBadge.astro +28 -0
- package/src/astro/components/AgendaTable.astro +49 -0
- package/src/astro/components/BodyBadge.astro +28 -0
- package/src/astro/components/CommitteeCard.astro +58 -0
- package/src/astro/components/CountryFlag.astro +34 -0
- package/src/astro/components/DecadeTimeline.astro +52 -0
- package/src/astro/components/DecisionList.astro +66 -0
- package/src/astro/components/EmptyState.astro +19 -0
- package/src/astro/components/LocaleTabs.astro +44 -0
- package/src/astro/components/MeetingList.astro +63 -0
- package/src/astro/components/MinutesSection.astro +59 -0
- package/src/astro/components/OfficerList.astro +49 -0
- package/src/astro/components/PageHero.astro +42 -0
- package/src/astro/components/PrevNextNav.astro +62 -0
- package/src/astro/components/ReferenceDocuments.astro +38 -0
- package/src/astro/components/UrnBar.astro +49 -0
- package/src/astro/layouts/BaseLayout.astro +79 -0
- package/src/astro/layouts/DecisionLayout.astro +21 -0
- package/src/astro/layouts/MeetingLayout.astro +21 -0
- package/src/astro/pages/404.astro +10 -0
- package/src/astro/pages/[lang]/about.astro +65 -0
- package/src/astro/pages/[lang]/decisions/[urn].astro +126 -0
- package/src/astro/pages/[lang]/decisions/index.astro +27 -0
- package/src/astro/pages/[lang]/index.astro +50 -0
- package/src/astro/pages/[lang]/meetings/[urn].astro +114 -0
- package/src/astro/pages/[lang]/meetings/index.astro +27 -0
- package/src/astro/pages/about.astro +65 -0
- package/src/astro/pages/decisions/[urn].astro +122 -0
- package/src/astro/pages/decisions/index.astro +67 -0
- package/src/astro/pages/index.astro +50 -0
- package/src/astro/pages/meetings/[urn].astro +110 -0
- package/src/astro/pages/meetings/index.astro +20 -0
- package/src/cli/index.ts +195 -0
- package/src/config/index.ts +33 -0
- package/src/config/paths.spec.ts +59 -0
- package/src/config/paths.ts +26 -0
- package/src/config/schema.spec.ts +263 -0
- package/src/config/schema.ts +132 -0
- package/src/config/tokens.spec.ts +57 -0
- package/src/config/tokens.ts +48 -0
- package/src/data/index.ts +36 -0
- package/src/data/lint.spec.ts +79 -0
- package/src/data/lint.ts +77 -0
- package/src/data/load.spec.ts +58 -0
- package/src/data/load.ts +50 -0
- package/src/data/prepare.spec.ts +137 -0
- package/src/data/prepare.ts +199 -0
- package/src/data/project.ts +11 -0
- package/src/data/validate.ts +38 -0
- package/src/errors.ts +25 -0
- package/src/i18n/index.spec.ts +121 -0
- package/src/i18n/index.ts +90 -0
- package/src/index.ts +74 -0
- package/src/integration.ts +233 -0
- package/src/islands/decade-scroller.ts +18 -0
- package/src/islands/print-button.ts +12 -0
- package/src/islands/search-filter-core.spec.ts +84 -0
- package/src/islands/search-filter-core.ts +89 -0
- package/src/islands/search-filter.ts +166 -0
- package/src/islands/section-tabs.ts +35 -0
- package/src/islands/theme-toggle.ts +33 -0
- package/src/islands/urn-copy.ts +29 -0
- package/src/seo/index.spec.ts +76 -0
- package/src/seo/index.ts +85 -0
- package/src/virtual.d.ts +11 -0
- package/styles/base.css +117 -0
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edoxen/browser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Astro-based browser for edoxen YAML data — drop in your data and ship a resolutions archive site.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "BSD-2-Clause",
|
|
7
|
+
"author": "Edoxen Project contributors",
|
|
8
|
+
"homepage": "https://github.com/edoxen/browser",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/edoxen/browser.git",
|
|
12
|
+
"directory": "packages/browser"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/edoxen/browser/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"astro",
|
|
19
|
+
"edoxen",
|
|
20
|
+
"resolutions",
|
|
21
|
+
"standards",
|
|
22
|
+
"iso",
|
|
23
|
+
"oiml"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"bin": {
|
|
27
|
+
"edoxen-browser": "./dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": "./src/index.ts",
|
|
31
|
+
"./config": "./src/config/index.ts",
|
|
32
|
+
"./data": "./src/data/index.ts",
|
|
33
|
+
"./seo": "./src/seo/index.ts",
|
|
34
|
+
"./i18n": "./src/i18n/index.ts",
|
|
35
|
+
"./integration": "./src/integration.ts",
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"main": "./src/index.ts",
|
|
39
|
+
"types": "./src/index.ts",
|
|
40
|
+
"files": [
|
|
41
|
+
"src/",
|
|
42
|
+
"styles/",
|
|
43
|
+
"dist/cli.js",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"dev": "astro dev",
|
|
49
|
+
"build": "astro build",
|
|
50
|
+
"build:cli": "tsup",
|
|
51
|
+
"prepublishOnly": "pnpm build:cli",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"typecheck": "tsc --noEmit"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@edoxen/edoxen": "^0.2.0",
|
|
58
|
+
"ajv": "^8.17.0",
|
|
59
|
+
"astro": "^4.0.0 || ^5.0.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@edoxen/edoxen": "link:../../../edoxen-js/packages/edoxen",
|
|
63
|
+
"@types/node": "^22.10.0",
|
|
64
|
+
"ajv": "^8.17.0",
|
|
65
|
+
"astro": "^5.0.0",
|
|
66
|
+
"tsup": "^8.3.5",
|
|
67
|
+
"typescript": "^5.6.3",
|
|
68
|
+
"vitest": "^2.1.0",
|
|
69
|
+
"yaml": "^2.6.0",
|
|
70
|
+
"zod": "^3.23.8"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"engines": {
|
|
76
|
+
"node": ">=20"
|
|
77
|
+
},
|
|
78
|
+
"dependencies": {
|
|
79
|
+
"@astrojs/sitemap": "^3.7.3",
|
|
80
|
+
"jiti": "^2.4.0"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { actionTypeColor, actionTypeLabel } from '@edoxen/edoxen'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
kind: string
|
|
6
|
+
}
|
|
7
|
+
const { kind } = Astro.props
|
|
8
|
+
const color = actionTypeColor(kind)
|
|
9
|
+
const label = actionTypeLabel(kind)
|
|
10
|
+
const style = color ? `background:${color};color:#fff` : undefined
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
{kind && (
|
|
14
|
+
<span class="edoxen-action-badge" style={style}>{label}</span>
|
|
15
|
+
)}
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.edoxen-action-badge {
|
|
19
|
+
display: inline-block;
|
|
20
|
+
padding: 0.15rem 0.55rem;
|
|
21
|
+
border-radius: var(--edoxen-radius-sm);
|
|
22
|
+
font-size: 0.8rem;
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
background: var(--edoxen-color-muted);
|
|
25
|
+
color: #fff;
|
|
26
|
+
text-transform: capitalize;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { AgendaItem } from '@edoxen/edoxen'
|
|
3
|
+
import { pickLocalizedValue } from '../../i18n/index.js'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
items: readonly AgendaItem[]
|
|
7
|
+
locale: string
|
|
8
|
+
}
|
|
9
|
+
const { items, locale } = Astro.props
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<table class="edoxen-agenda">
|
|
13
|
+
<thead>
|
|
14
|
+
<tr><th scope="col">#</th><th scope="col">Title</th><th scope="col">Outcome</th></tr>
|
|
15
|
+
</thead>
|
|
16
|
+
<tbody>
|
|
17
|
+
{items.map((item) => (
|
|
18
|
+
<tr>
|
|
19
|
+
<td><code>{item.label}</code></td>
|
|
20
|
+
<td>{pickLocalizedValue(item.title, locale, item.label ?? '')}</td>
|
|
21
|
+
<td>{item.outcome ?? ''}</td>
|
|
22
|
+
</tr>
|
|
23
|
+
))}
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
26
|
+
|
|
27
|
+
<style>
|
|
28
|
+
.edoxen-agenda {
|
|
29
|
+
width: 100%;
|
|
30
|
+
border-collapse: collapse;
|
|
31
|
+
font-size: 0.95rem;
|
|
32
|
+
}
|
|
33
|
+
.edoxen-agenda th,
|
|
34
|
+
.edoxen-agenda td {
|
|
35
|
+
text-align: left;
|
|
36
|
+
padding: 0.5rem 0.75rem;
|
|
37
|
+
border-bottom: 1px solid var(--edoxen-color-border);
|
|
38
|
+
}
|
|
39
|
+
.edoxen-agenda th {
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
color: var(--edoxen-color-muted);
|
|
42
|
+
text-transform: uppercase;
|
|
43
|
+
font-size: 0.75rem;
|
|
44
|
+
letter-spacing: 0.05em;
|
|
45
|
+
}
|
|
46
|
+
.edoxen-agenda code {
|
|
47
|
+
font-family: var(--edoxen-font-mono, ui-monospace, monospace);
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
import cfg from 'virtual:edoxen-config'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
code?: string
|
|
6
|
+
}
|
|
7
|
+
const { code } = Astro.props
|
|
8
|
+
const body = code ? cfg.bodies.find((b) => b.code === code) : undefined
|
|
9
|
+
const style = body?.color
|
|
10
|
+
? `background:${body.color};color:${body.textColor ?? '#ffffff'}`
|
|
11
|
+
: undefined
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{code && (
|
|
15
|
+
<span class="edoxen-badge" style={style}>{body?.name ?? code}</span>
|
|
16
|
+
)}
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
.edoxen-badge {
|
|
20
|
+
display: inline-block;
|
|
21
|
+
padding: 0.15rem 0.55rem;
|
|
22
|
+
border-radius: var(--edoxen-radius-sm);
|
|
23
|
+
font-size: 0.8rem;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
background: var(--edoxen-color-muted);
|
|
26
|
+
color: #fff;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { MeetingSeries } from '@edoxen/edoxen'
|
|
3
|
+
import { pickLocalizedValue } from '../../i18n/index.js'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
committee?: MeetingSeries | null
|
|
7
|
+
locale: string
|
|
8
|
+
}
|
|
9
|
+
const { committee, locale } = Astro.props
|
|
10
|
+
const name = committee ? pickLocalizedValue(committee.name, locale, committee.urn ?? 'Committee') : ''
|
|
11
|
+
const description = committee ? pickLocalizedValue(committee.description, locale) : ''
|
|
12
|
+
const identifiers = committee?.identifier ?? []
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
{committee && (
|
|
16
|
+
<article class="edoxen-committee-card">
|
|
17
|
+
{name && <h2 class="edoxen-committee-card__name">{name}</h2>}
|
|
18
|
+
{description && <p class="edoxen-committee-card__desc">{description}</p>}
|
|
19
|
+
{identifiers.length > 0 && (
|
|
20
|
+
<dl class="edoxen-committee-card__ids">
|
|
21
|
+
{identifiers.map((id) => (
|
|
22
|
+
<>
|
|
23
|
+
<dt>{id.prefix}</dt>
|
|
24
|
+
<dd>{id.number}</dd>
|
|
25
|
+
</>
|
|
26
|
+
))}
|
|
27
|
+
</dl>
|
|
28
|
+
)}
|
|
29
|
+
</article>
|
|
30
|
+
)}
|
|
31
|
+
|
|
32
|
+
<style>
|
|
33
|
+
.edoxen-committee-card {
|
|
34
|
+
border: 1px solid var(--edoxen-color-border);
|
|
35
|
+
border-radius: var(--edoxen-radius-sm);
|
|
36
|
+
background: var(--edoxen-color-surface);
|
|
37
|
+
padding: 1rem 1.25rem;
|
|
38
|
+
}
|
|
39
|
+
.edoxen-committee-card__name {
|
|
40
|
+
margin: 0 0 0.5rem;
|
|
41
|
+
font-size: 1.1rem;
|
|
42
|
+
}
|
|
43
|
+
.edoxen-committee-card__desc {
|
|
44
|
+
margin: 0 0 0.75rem;
|
|
45
|
+
color: var(--edoxen-color-text);
|
|
46
|
+
}
|
|
47
|
+
.edoxen-committee-card__ids {
|
|
48
|
+
display: grid;
|
|
49
|
+
grid-template-columns: auto 1fr;
|
|
50
|
+
gap: 0.25rem 0.75rem;
|
|
51
|
+
margin: 0;
|
|
52
|
+
font-size: 0.85rem;
|
|
53
|
+
color: var(--edoxen-color-muted);
|
|
54
|
+
}
|
|
55
|
+
.edoxen-committee-card__ids dt {
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { countryFlag } from '@edoxen/edoxen'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
countryCode?: string
|
|
6
|
+
city?: string
|
|
7
|
+
}
|
|
8
|
+
const { countryCode, city } = Astro.props
|
|
9
|
+
const flag = countryCode ? countryFlag(countryCode) : ''
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
{(city || countryCode) && (
|
|
13
|
+
<span class="edoxen-venue">
|
|
14
|
+
{flag && <span class="edoxen-venue__flag" aria-hidden="true">{flag}</span>}
|
|
15
|
+
{city && <span class="edoxen-venue__city">{city}</span>}
|
|
16
|
+
{countryCode && <span class="edoxen-venue__code">{countryCode}</span>}
|
|
17
|
+
</span>
|
|
18
|
+
)}
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.edoxen-venue {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
gap: 0.4rem;
|
|
24
|
+
align-items: center;
|
|
25
|
+
}
|
|
26
|
+
.edoxen-venue__flag {
|
|
27
|
+
font-size: 1.2em;
|
|
28
|
+
}
|
|
29
|
+
.edoxen-venue__code {
|
|
30
|
+
color: var(--edoxen-color-muted);
|
|
31
|
+
font-size: 0.85em;
|
|
32
|
+
font-family: var(--edoxen-font-mono, ui-monospace, monospace);
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
decades: readonly number[]
|
|
4
|
+
active?: number
|
|
5
|
+
}
|
|
6
|
+
const { decades, active } = Astro.props
|
|
7
|
+
const sorted = [...decades].sort((a, b) => b - a)
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{sorted.length > 0 && (
|
|
11
|
+
<nav class="edoxen-decade-timeline" aria-label="Browse by decade">
|
|
12
|
+
{sorted.map((d) => (
|
|
13
|
+
<a
|
|
14
|
+
href={`#decade-${d}`}
|
|
15
|
+
class={`edoxen-decade-timeline__link${active === d ? ' edoxen-decade-timeline__link--active' : ''}`}
|
|
16
|
+
>
|
|
17
|
+
<span class="edoxen-decade-timeline__decade">{d}s</span>
|
|
18
|
+
</a>
|
|
19
|
+
))}
|
|
20
|
+
</nav>
|
|
21
|
+
)}
|
|
22
|
+
|
|
23
|
+
<style>
|
|
24
|
+
.edoxen-decade-timeline {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-wrap: wrap;
|
|
27
|
+
gap: 0.5rem;
|
|
28
|
+
margin-bottom: 1.5rem;
|
|
29
|
+
font-size: 0.85rem;
|
|
30
|
+
}
|
|
31
|
+
.edoxen-decade-timeline__link {
|
|
32
|
+
padding: 0.3rem 0.7rem;
|
|
33
|
+
border: 1px solid var(--edoxen-color-border);
|
|
34
|
+
border-radius: var(--edoxen-radius-sm);
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
color: var(--edoxen-color-text);
|
|
37
|
+
background: var(--edoxen-color-surface);
|
|
38
|
+
}
|
|
39
|
+
.edoxen-decade-timeline__link:hover {
|
|
40
|
+
background: var(--edoxen-color-accent);
|
|
41
|
+
color: #fff;
|
|
42
|
+
border-color: var(--edoxen-color-accent);
|
|
43
|
+
}
|
|
44
|
+
.edoxen-decade-timeline__link--active {
|
|
45
|
+
background: var(--edoxen-color-accent);
|
|
46
|
+
color: #fff;
|
|
47
|
+
border-color: var(--edoxen-color-accent);
|
|
48
|
+
}
|
|
49
|
+
.edoxen-decade-timeline__decade {
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { DecisionListItem } from '../../data/index.js'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
items: readonly DecisionListItem[]
|
|
6
|
+
compact?: boolean
|
|
7
|
+
}
|
|
8
|
+
const { items, compact = false } = Astro.props
|
|
9
|
+
const listClass = compact ? 'edoxen-decision-list edoxen-decision-list--compact' : 'edoxen-decision-list'
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
{items.length === 0 ? (
|
|
13
|
+
<p class="edoxen-empty">No decisions.</p>
|
|
14
|
+
) : (
|
|
15
|
+
<ul class={listClass}>
|
|
16
|
+
{items.map((d) => (
|
|
17
|
+
<li class="edoxen-decision-list__item">
|
|
18
|
+
<a href={`/decisions/${encodeURIComponent(d.urn)}`}>{d.title}</a>
|
|
19
|
+
{!compact && (
|
|
20
|
+
<dl class="edoxen-decision-list__meta">
|
|
21
|
+
<dt>URN</dt>
|
|
22
|
+
<dd><code>{d.urn}</code></dd>
|
|
23
|
+
{d.bodyType && <><dt>Body</dt><dd>{d.bodyType}</dd></>}
|
|
24
|
+
{d.kind && <><dt>Kind</dt><dd>{d.kind}</dd></>}
|
|
25
|
+
{d.dates[0]?.date && <><dt>Date</dt><dd>{d.dates[0].date}</dd></>}
|
|
26
|
+
</dl>
|
|
27
|
+
)}
|
|
28
|
+
</li>
|
|
29
|
+
))}
|
|
30
|
+
</ul>
|
|
31
|
+
)}
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.edoxen-decision-list {
|
|
35
|
+
list-style: none;
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
gap: 0.75rem;
|
|
41
|
+
}
|
|
42
|
+
.edoxen-decision-list__item {
|
|
43
|
+
padding: 0.75rem 1rem;
|
|
44
|
+
border: 1px solid var(--edoxen-color-border);
|
|
45
|
+
border-radius: var(--edoxen-radius-sm);
|
|
46
|
+
background: var(--edoxen-color-surface);
|
|
47
|
+
}
|
|
48
|
+
.edoxen-decision-list__item a {
|
|
49
|
+
font-weight: 500;
|
|
50
|
+
color: var(--edoxen-color-text);
|
|
51
|
+
}
|
|
52
|
+
.edoxen-decision-list__meta {
|
|
53
|
+
display: grid;
|
|
54
|
+
grid-template-columns: auto 1fr;
|
|
55
|
+
gap: 0.25rem 1rem;
|
|
56
|
+
margin: 0.5rem 0 0;
|
|
57
|
+
font-size: 0.85rem;
|
|
58
|
+
color: var(--edoxen-color-muted);
|
|
59
|
+
}
|
|
60
|
+
.edoxen-decision-list__meta dt {
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
}
|
|
63
|
+
.edoxen-decision-list--compact .edoxen-decision-list__item {
|
|
64
|
+
padding: 0.5rem 0.75rem;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
message?: string
|
|
4
|
+
}
|
|
5
|
+
const { message = 'Nothing here.' } = Astro.props
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<p class="edoxen-empty-state">{message}</p>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
.edoxen-empty-state {
|
|
12
|
+
padding: 2rem 1rem;
|
|
13
|
+
text-align: center;
|
|
14
|
+
color: var(--edoxen-color-muted);
|
|
15
|
+
border: 1px dashed var(--edoxen-color-border);
|
|
16
|
+
border-radius: var(--edoxen-radius-sm);
|
|
17
|
+
background: var(--edoxen-color-surface);
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
spellings: readonly string[]
|
|
4
|
+
active: string
|
|
5
|
+
field: string
|
|
6
|
+
}
|
|
7
|
+
const { spellings, active, field } = Astro.props
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{spellings.length > 1 && (
|
|
11
|
+
<nav class="edoxen-locale-tabs" aria-label={`Available languages for ${field}`} data-field={field}>
|
|
12
|
+
{spellings.map((sp) => (
|
|
13
|
+
<button type="button" class="edoxen-locale-tabs__tab" data-spelling={sp} aria-pressed={sp === active}>
|
|
14
|
+
{sp}
|
|
15
|
+
</button>
|
|
16
|
+
))}
|
|
17
|
+
</nav>
|
|
18
|
+
)}
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.edoxen-locale-tabs {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
gap: 0.25rem;
|
|
24
|
+
margin: 0.5rem 0 1rem;
|
|
25
|
+
padding: 0.25rem;
|
|
26
|
+
border: 1px solid var(--edoxen-color-border);
|
|
27
|
+
border-radius: var(--edoxen-radius-sm);
|
|
28
|
+
background: var(--edoxen-color-surface);
|
|
29
|
+
}
|
|
30
|
+
.edoxen-locale-tabs__tab {
|
|
31
|
+
border: 0;
|
|
32
|
+
background: transparent;
|
|
33
|
+
color: var(--edoxen-color-muted);
|
|
34
|
+
padding: 0.25rem 0.6rem;
|
|
35
|
+
border-radius: calc(var(--edoxen-radius-sm) * 0.75);
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
font-size: 0.8rem;
|
|
38
|
+
font-family: var(--edoxen-font-mono, ui-monospace, monospace);
|
|
39
|
+
}
|
|
40
|
+
.edoxen-locale-tabs__tab[aria-pressed='true'] {
|
|
41
|
+
background: var(--edoxen-color-accent);
|
|
42
|
+
color: #fff;
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { MeetingListItem } from '../../data/index.js'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
items: readonly MeetingListItem[]
|
|
6
|
+
compact?: boolean
|
|
7
|
+
}
|
|
8
|
+
const { items, compact = false } = Astro.props
|
|
9
|
+
const listClass = compact ? 'edoxen-meeting-list edoxen-meeting-list--compact' : 'edoxen-meeting-list'
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
{items.length === 0 ? (
|
|
13
|
+
<p class="edoxen-empty">No meetings.</p>
|
|
14
|
+
) : (
|
|
15
|
+
<ul class={listClass}>
|
|
16
|
+
{items.map((m) => (
|
|
17
|
+
<li class="edoxen-meeting-list__item">
|
|
18
|
+
<a href={`/meetings/${encodeURIComponent(m.urn)}`}>{m.title}</a>
|
|
19
|
+
{!compact && (
|
|
20
|
+
<dl class="edoxen-meeting-list__meta">
|
|
21
|
+
<dt>URN</dt>
|
|
22
|
+
<dd><code>{m.urn}</code></dd>
|
|
23
|
+
{m.startDate && <><dt>Start</dt><dd>{m.startDate}</dd></>}
|
|
24
|
+
{m.city && <><dt>Venue</dt><dd>{m.city}{m.countryCode && ` (${m.countryCode})`}</dd></>}
|
|
25
|
+
{m.bodyType && <><dt>Body</dt><dd>{m.bodyType}</dd></>}
|
|
26
|
+
</dl>
|
|
27
|
+
)}
|
|
28
|
+
</li>
|
|
29
|
+
))}
|
|
30
|
+
</ul>
|
|
31
|
+
)}
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.edoxen-meeting-list {
|
|
35
|
+
list-style: none;
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
gap: 0.75rem;
|
|
41
|
+
}
|
|
42
|
+
.edoxen-meeting-list__item {
|
|
43
|
+
padding: 0.75rem 1rem;
|
|
44
|
+
border: 1px solid var(--edoxen-color-border);
|
|
45
|
+
border-radius: var(--edoxen-radius-sm);
|
|
46
|
+
background: var(--edoxen-color-surface);
|
|
47
|
+
}
|
|
48
|
+
.edoxen-meeting-list__item a {
|
|
49
|
+
font-weight: 500;
|
|
50
|
+
color: var(--edoxen-color-text);
|
|
51
|
+
}
|
|
52
|
+
.edoxen-meeting-list__meta {
|
|
53
|
+
display: grid;
|
|
54
|
+
grid-template-columns: auto 1fr;
|
|
55
|
+
gap: 0.25rem 1rem;
|
|
56
|
+
margin: 0.5rem 0 0;
|
|
57
|
+
font-size: 0.85rem;
|
|
58
|
+
color: var(--edoxen-color-muted);
|
|
59
|
+
}
|
|
60
|
+
.edoxen-meeting-list__meta dt {
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { Minutes} from '@edoxen/edoxen'
|
|
3
|
+
import { pickLocalizedValue } from '../../i18n/index.js'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
minutes: Minutes
|
|
7
|
+
locale: string
|
|
8
|
+
}
|
|
9
|
+
const { minutes, locale } = Astro.props
|
|
10
|
+
const sections = minutes.sections ?? []
|
|
11
|
+
const spelling = minutes.spelling ?? locale
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<article class="edoxen-minutes" data-spelling={spelling}>
|
|
15
|
+
<header>
|
|
16
|
+
<h3>Minutes{spelling ? ` — ${spelling}` : ''}</h3>
|
|
17
|
+
{minutes.urn && <p><code>{minutes.urn}</code></p>}
|
|
18
|
+
</header>
|
|
19
|
+
{sections.map((section) => (
|
|
20
|
+
<section class="edoxen-minutes__section">
|
|
21
|
+
<h4>{section.number}. {pickLocalizedValue(section.title, locale, '(untitled)')}</h4>
|
|
22
|
+
<div class="edoxen-minutes__narrative">
|
|
23
|
+
{pickLocalizedValue(section.narrative, locale)}
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
))}
|
|
27
|
+
</article>
|
|
28
|
+
|
|
29
|
+
<style>
|
|
30
|
+
.edoxen-minutes {
|
|
31
|
+
border: 1px solid var(--edoxen-color-border);
|
|
32
|
+
border-radius: var(--edoxen-radius-sm);
|
|
33
|
+
padding: 1rem 1.25rem;
|
|
34
|
+
background: var(--edoxen-color-surface);
|
|
35
|
+
margin-bottom: 1rem;
|
|
36
|
+
}
|
|
37
|
+
.edoxen-minutes h3 {
|
|
38
|
+
margin: 0 0 0.5rem;
|
|
39
|
+
font-size: 1.05rem;
|
|
40
|
+
}
|
|
41
|
+
.edoxen-minutes__section {
|
|
42
|
+
margin-top: 1rem;
|
|
43
|
+
}
|
|
44
|
+
.edoxen-minutes__section h4 {
|
|
45
|
+
margin: 0 0 0.5rem;
|
|
46
|
+
font-size: 0.95rem;
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
}
|
|
49
|
+
.edoxen-minutes__narrative {
|
|
50
|
+
font-size: 0.95rem;
|
|
51
|
+
line-height: 1.5;
|
|
52
|
+
white-space: pre-wrap;
|
|
53
|
+
color: var(--edoxen-color-text);
|
|
54
|
+
}
|
|
55
|
+
.edoxen-minutes code {
|
|
56
|
+
font-family: var(--edoxen-font-mono, ui-monospace, monospace);
|
|
57
|
+
font-size: 0.85rem;
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { Officer } from '@edoxen/edoxen'
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
officers: readonly Officer[]
|
|
6
|
+
}
|
|
7
|
+
const { officers } = Astro.props
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
{officers.length > 0 && (
|
|
11
|
+
<ul class="edoxen-officer-list">
|
|
12
|
+
{officers.map((o) => (
|
|
13
|
+
<li class="edoxen-officer-list__item">
|
|
14
|
+
<span class="edoxen-officer-list__role">{o.role}</span>
|
|
15
|
+
{o.person && (
|
|
16
|
+
<span class="edoxen-officer-list__name">
|
|
17
|
+
{o.person.name?.map((n) => n.value).filter(Boolean).join(' ') || ''}
|
|
18
|
+
</span>
|
|
19
|
+
)}
|
|
20
|
+
</li>
|
|
21
|
+
))}
|
|
22
|
+
</ul>
|
|
23
|
+
)}
|
|
24
|
+
|
|
25
|
+
<style>
|
|
26
|
+
.edoxen-officer-list {
|
|
27
|
+
list-style: none;
|
|
28
|
+
padding: 0;
|
|
29
|
+
margin: 0;
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: 0.4rem;
|
|
33
|
+
}
|
|
34
|
+
.edoxen-officer-list__item {
|
|
35
|
+
display: flex;
|
|
36
|
+
gap: 0.75rem;
|
|
37
|
+
padding: 0.4rem 0;
|
|
38
|
+
border-bottom: 1px solid var(--edoxen-color-border);
|
|
39
|
+
}
|
|
40
|
+
.edoxen-officer-list__role {
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
text-transform: capitalize;
|
|
43
|
+
min-width: 8rem;
|
|
44
|
+
color: var(--edoxen-color-muted);
|
|
45
|
+
}
|
|
46
|
+
.edoxen-officer-list__name {
|
|
47
|
+
color: var(--edoxen-color-text);
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string
|
|
4
|
+
subtitle?: string
|
|
5
|
+
logo?: string
|
|
6
|
+
}
|
|
7
|
+
const { title, subtitle, logo } = Astro.props
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<header class="edoxen-page-hero">
|
|
11
|
+
{logo && <img src={logo} alt="" class="edoxen-page-hero__logo" />}
|
|
12
|
+
<div>
|
|
13
|
+
<h1 class="edoxen-page-hero__title">{title}</h1>
|
|
14
|
+
{subtitle && <p class="edoxen-page-hero__subtitle">{subtitle}</p>}
|
|
15
|
+
</div>
|
|
16
|
+
</header>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
.edoxen-page-hero {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: 1.5rem;
|
|
23
|
+
padding: 2rem 0;
|
|
24
|
+
margin-bottom: 1.5rem;
|
|
25
|
+
border-bottom: 1px solid var(--edoxen-color-border);
|
|
26
|
+
}
|
|
27
|
+
.edoxen-page-hero__logo {
|
|
28
|
+
max-height: 4rem;
|
|
29
|
+
width: auto;
|
|
30
|
+
}
|
|
31
|
+
.edoxen-page-hero__title {
|
|
32
|
+
margin: 0;
|
|
33
|
+
font-size: 2rem;
|
|
34
|
+
font-weight: 700;
|
|
35
|
+
letter-spacing: -0.01em;
|
|
36
|
+
}
|
|
37
|
+
.edoxen-page-hero__subtitle {
|
|
38
|
+
margin: 0.25rem 0 0;
|
|
39
|
+
color: var(--edoxen-color-muted);
|
|
40
|
+
font-size: 1.05rem;
|
|
41
|
+
}
|
|
42
|
+
</style>
|