@master/internal-site 0.1.2 → 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/README.md +43 -0
- package/dist/astro.mjs +233 -47
- package/dist/config.d.mts +6 -0
- package/dist/localization-LfIbIysE.mjs +356 -0
- package/dist/localization.d.mts +69 -0
- package/dist/localization.mjs +1 -0
- package/package.json +12 -9
- package/src/astro/content-pages.ts +30 -11
- package/src/astro/index.ts +11 -5
- package/src/astro/localized-mdx.ts +45 -0
- package/src/astro/routes.template.ts +4 -0
- package/src/astro/site-context.ts +10 -2
- package/src/astro/style-assets.ts +107 -0
- package/src/benchmarks/BenchmarkBarRows.astro +3 -2
- package/src/benchmarks/BenchmarkBars.astro +1 -1
- package/src/benchmarks/BenchmarkChart.astro +5 -1
- package/src/benchmarks/BenchmarkChartGroup.astro +1 -1
- package/src/benchmarks/BenchmarkDataTable.astro +1 -1
- package/src/benchmarks/BenchmarkFigure.astro +2 -1
- package/src/benchmarks/BenchmarkMetricTable.astro +2 -2
- package/src/benchmarks/BenchmarkMetrics.astro +1 -1
- package/src/benchmarks/BenchmarkSampleSummary.astro +1 -1
- package/src/benchmarks/BenchmarkScrollRegion.svelte +2 -1
- package/src/benchmarks/BenchmarkSource.astro +1 -1
- package/src/benchmarks/BenchmarkStackedBars.astro +4 -3
- package/src/benchmarks/BenchmarkStatus.astro +3 -1
- package/src/benchmarks/localization.ts +22 -0
- package/src/benchmarks/types.ts +2 -0
- package/src/blog/article/BlogArticleContents.svelte +1 -1
- package/src/blog/article/BlogArticleEnd.astro +6 -9
- package/src/blog/article/BlogArticleMasthead.astro +17 -9
- package/src/config.ts +3 -0
- package/src/css/NamespaceUtilityTable.astro +1 -1
- package/src/css/ThemeNumberVariableTable.astro +1 -1
- package/src/css/foundation-data/specimen-content.ts +2 -2
- package/src/css/markdown.ts +64 -14
- package/src/demo/Demo.svelte +10 -4
- package/src/demo/DemoAsset.astro +6 -3
- package/src/demo/DemoAxes.svelte +4 -2
- package/src/demo/DemoCatalog.astro +9 -6
- package/src/demo/DemoComparison.svelte +3 -0
- package/src/demo/DemoContainer.svelte +8 -3
- package/src/demo/DemoControls.svelte +5 -1
- package/src/demo/DemoCopyButton.svelte +9 -4
- package/src/demo/DemoCopyGroup.svelte +6 -2
- package/src/demo/DemoExample.astro +3 -1
- package/src/demo/DemoFeatureSupport.svelte +5 -1
- package/src/demo/DemoGeneratedCSS.svelte +5 -1
- package/src/demo/DemoIndex.astro +6 -3
- package/src/demo/DemoLegend.svelte +3 -1
- package/src/demo/DemoMeasure.svelte +4 -2
- package/src/demo/DemoMedia.svelte +3 -1
- package/src/demo/DemoMotion.svelte +6 -3
- package/src/demo/DemoPaletteGroups.svelte +4 -2
- package/src/demo/DemoScrollArea.svelte +2 -0
- package/src/demo/DemoStyleComparison.astro +6 -3
- package/src/demo/DemoSurface.svelte +2 -0
- package/src/demo/DemoThemeComparison.astro +5 -2
- package/src/demo/DemoTokenTable.astro +5 -3
- package/src/demo/DemoViewTransition.astro +3 -1
- package/src/demo/DemoViewport.svelte +18 -11
- package/src/demo/DemoWaterfall.astro +4 -2
- package/src/demo/ProjectStyleExample.astro +4 -1
- package/src/demo/foundations/FoundationDialog.astro +6 -2
- package/src/demo/foundations/FoundationMedia.astro +1 -0
- package/src/demo/foundations/FoundationShrink.astro +1 -0
- package/src/demo/foundations/FoundationTokensView.astro +16 -5
- package/src/demo/foundations/Palette.svelte +11 -7
- package/src/demo/foundations/dialog-copy.d.ts +1 -0
- package/src/demo/foundations/dialog-copy.js +5 -0
- package/src/demo/illustration-materials.ts +1 -1
- package/src/demo/illustration.css +218 -0
- package/src/docs-shell/common/i18n.config.d.ts +1 -1
- package/src/docs-shell/common/i18n.config.js +4 -12
- package/src/docs-shell/common/locales.d.ts +8 -0
- package/src/docs-shell/common/locales.js +18 -0
- package/src/docs-shell/common/terminology.json +32 -0
- package/src/docs-shell/common/translations.d.ts +3 -0
- package/src/docs-shell/common/translations.js +294 -0
- package/src/docs-shell/components/ArticleHeader.astro +5 -3
- package/src/docs-shell/components/Callout.astro +1 -0
- package/src/docs-shell/components/CodeCopyButton.astro +5 -1
- package/src/docs-shell/components/CodeTabBar.astro +7 -3
- package/src/docs-shell/components/CodeTabs.astro +2 -1
- package/src/docs-shell/components/CodeView.astro +1 -1
- package/src/docs-shell/components/DocHeader.svelte +13 -17
- package/src/docs-shell/components/DocHeading.astro +3 -1
- package/src/docs-shell/components/DocMenuButton.svelte +126 -61
- package/src/docs-shell/components/DocSidebar.svelte +3 -2
- package/src/docs-shell/components/DocVersionSelect.svelte +2 -0
- package/src/docs-shell/components/DocumentAPIIndex.astro +1 -1
- package/src/docs-shell/components/DocumentChoices.astro +1 -1
- package/src/docs-shell/components/DocumentCodeExampleView.astro +3 -1
- package/src/docs-shell/components/DocumentCodeTable.astro +4 -2
- package/src/docs-shell/components/DocumentCopyButton.svelte +3 -0
- package/src/docs-shell/components/DocumentDisclosure.astro +2 -0
- package/src/docs-shell/components/DocumentFileTree.astro +3 -0
- package/src/docs-shell/components/DocumentFlow.astro +4 -1
- package/src/docs-shell/components/DocumentIllustration.astro +8 -12
- package/src/docs-shell/components/DocumentKeyList.astro +6 -4
- package/src/docs-shell/components/DocumentNamespaceTable.astro +5 -3
- package/src/docs-shell/components/DocumentOptionEntry.astro +0 -1
- package/src/docs-shell/components/DocumentOptionList.astro +1 -1
- package/src/docs-shell/components/DocumentOptions.astro +3 -2
- package/src/docs-shell/components/DocumentParameters.astro +1 -1
- package/src/docs-shell/components/DocumentPrompt.astro +2 -0
- package/src/docs-shell/components/DocumentValueList.astro +1 -1
- package/src/docs-shell/components/DocumentationIndex.svelte +8 -7
- package/src/docs-shell/components/ExpandContent.svelte +3 -0
- package/src/docs-shell/components/ExplorerView.astro +1 -0
- package/src/docs-shell/components/GeneratedCSS.astro +4 -1
- package/src/docs-shell/components/Header.svelte +1 -1
- package/src/docs-shell/components/InlineCode.astro +1 -0
- package/src/docs-shell/components/InteractingIndicator.astro +1 -0
- package/src/docs-shell/components/LanguageButton.svelte +1 -0
- package/src/docs-shell/components/LanguageSelect.svelte +2 -0
- package/src/docs-shell/components/Link.svelte +3 -2
- package/src/docs-shell/components/NotFound.astro +6 -4
- package/src/docs-shell/components/PMAction.astro +1 -0
- package/src/docs-shell/components/PageContent.svelte +1 -1
- package/src/docs-shell/components/PageContentDisclosure.astro +2 -1
- package/src/docs-shell/components/PageContentList.svelte +2 -0
- package/src/docs-shell/components/PageNavs.astro +3 -3
- package/src/docs-shell/components/SearchButton.svelte +3 -0
- package/src/docs-shell/components/SearchDialog.svelte +18 -16
- package/src/docs-shell/components/Segments.svelte +2 -0
- package/src/docs-shell/components/StepSection.astro +1 -2
- package/src/docs-shell/components/Tabs.astro +1 -0
- package/src/docs-shell/components/ThemeSelect.svelte +2 -0
- package/src/docs-shell/components/TimeAgo.svelte +6 -6
- package/src/docs-shell/components/markdown/Table.astro +1 -0
- package/src/docs-shell/components/markdown-components.ts +0 -1
- package/src/docs-shell/contexts/search.ts +1 -1
- package/src/docs-shell/factories/Page.astro +10 -5
- package/src/docs-shell/factories/create-page.ts +33 -6
- package/src/docs-shell/layouts/BlogArticle.astro +3 -11
- package/src/docs-shell/remark/markdown-components.js +28 -7
- package/src/docs-shell/remark/slug-and-toc.js +5 -7
- package/src/docs-shell/scripts/code.ts +5 -2
- package/src/docs-shell/scripts/document.ts +1 -1
- package/src/docs-shell/site.ts +9 -1
- package/src/docs-shell/types/Metadata.ts +11 -0
- package/src/docs-shell/utils/document-copy.d.ts +2 -0
- package/src/docs-shell/utils/document-copy.js +18 -0
- package/src/docs-shell/utils/generate-metadata.ts +5 -1
- package/src/docs-shell/utils/head.ts +5 -2
- package/src/docs-shell/utils/i18n-pathname.ts +13 -2
- package/src/docs-shell/utils/i18n.ts +4 -1
- package/src/docs-shell/utils/localized-metadata.ts +22 -0
- package/src/docs-shell/utils/markdown-links.ts +61 -0
- package/src/docs-shell/utils/markdown-tree.ts +19 -6
- package/src/docs-shell/utils/resolve-heading.d.ts +1 -0
- package/src/docs-shell/utils/resolve-heading.js +21 -0
- package/src/docs-shell/utils/search-pages.ts +75 -22
- package/src/examples/components/ArticleTransitionScene.svelte +4 -0
- package/src/examples/layout-system/page.astro +0 -1
- package/src/home/HomeBentoFrame.astro +1 -0
- package/src/home/HomeBentoGrid.astro +1 -0
- package/src/home/bento.css +167 -0
- package/src/home/design.css +1 -1
- package/src/home/hero.css +5 -0
- package/src/home/home.css +4 -576
- package/src/home/segmented-control.css +94 -0
- package/src/layouts/Document.astro +4 -2
- package/src/public/icons/json.svg +1 -0
- package/src/scripts/atomic-class-authoring.ts +98 -0
- package/src/scripts/localization.ts +239 -0
- package/src/scripts/mdx-sample.ts +12 -0
- package/src/scripts/static-social.ts +17 -3
- package/src/scripts/style-delivery.mjs +120 -0
- package/src/sections/blog.astro +1 -1
- package/src/sections/guide.astro +4 -3
- package/src/styles/blog-article.css +10 -7
- package/src/styles/blog-materials.css +13 -0
- package/src/styles/demo.css +0 -1
- package/src/styles/docs-shell/code.css +5 -61
- package/src/styles/docs-shell/documentation-search.css +1 -0
- package/src/styles/docs-shell/header.css +2 -73
- package/src/styles/docs-shell/menu.css +37 -17
- package/src/styles/docs-shell/page-content.css +2 -37
- package/src/styles/docs-shell/prose.css +18 -9
- package/src/styles/docs-shell/steps.css +2 -39
- package/src/styles/document-comparison.css +5 -2
- package/src/styles/documentation-illustration.css +1 -9
- package/src/styles/documentation-index.css +2 -1
- package/src/styles/documents.css +2 -4
- package/src/styles/interface.css +5 -3
- package/src/styles/system/DESIGN.md +34 -14
- package/src/styles/system/browser.css +21 -0
- package/src/styles/system/button-feedback.css +13 -0
- package/src/styles/system/callout.css +14 -0
- package/src/styles/system/chart.css +18 -0
- package/src/styles/system/checks.css +18 -0
- package/src/styles/system/code-panel.css +82 -0
- package/src/styles/system/code-tabs.css +40 -0
- package/src/styles/system/code.css +8 -85
- package/src/styles/system/compare.css +7 -0
- package/src/styles/system/controls.css +10 -109
- package/src/styles/system/copy.css +32 -0
- package/src/styles/system/data.css +10 -134
- package/src/styles/system/dialog.css +16 -0
- package/src/styles/system/disclosure.css +19 -0
- package/src/styles/system/expand.css +11 -0
- package/src/styles/system/fields.css +25 -0
- package/src/styles/system/header-core.css +101 -0
- package/src/styles/system/hint.css +5 -0
- package/src/styles/system/index.css +13 -0
- package/src/styles/system/inline-code.css +4 -0
- package/src/styles/system/kbd.css +4 -0
- package/src/styles/system/logos.css +10 -0
- package/src/styles/system/menu.css +14 -0
- package/src/styles/system/metrics.css +22 -0
- package/src/styles/system/pagehead.css +13 -0
- package/src/styles/system/pager.css +13 -0
- package/src/styles/system/parameters.css +17 -0
- package/src/styles/system/prompt.css +7 -0
- package/src/styles/system/prose.css +4 -75
- package/src/styles/system/range.css +12 -0
- package/src/styles/system/reading.css +44 -0
- package/src/styles/system/scroll.css +6 -0
- package/src/styles/system/search-trigger.css +10 -0
- package/src/styles/system/segmented.css +22 -0
- package/src/styles/system/sheet.css +8 -0
- package/src/styles/system/shell.css +8 -102
- package/src/styles/system/sidebar.css +14 -0
- package/src/styles/system/source.css +5 -0
- package/src/styles/system/specimens.css +3 -0
- package/src/styles/system/stage.css +18 -0
- package/src/styles/system/steps.css +51 -0
- package/src/styles/system/surfaces.css +8 -104
- package/src/styles/system/table.css +23 -0
- package/src/styles/system/toc.css +59 -0
- package/src/styles/system/tooltip.css +6 -0
- package/src/styles/system/tray-code.css +6 -0
- package/src/styles/system/tray.css +20 -0
- package/src/styles/system/tree.css +15 -0
- package/src/styles/system/waterfall.css +14 -0
- package/src/virtual.d.ts +5 -1
- package/src/blog/article/language.ts +0 -29
package/src/css/markdown.ts
CHANGED
|
@@ -6,6 +6,10 @@ import { mdxjsEsmFromMarkdown } from 'mdast-util-mdxjs-esm'
|
|
|
6
6
|
import { mdxJsx } from 'micromark-extension-mdx-jsx'
|
|
7
7
|
import { mdxJsxFromMarkdown } from 'mdast-util-mdx-jsx'
|
|
8
8
|
import * as acorn from 'acorn'
|
|
9
|
+
import { parseFrontmatter } from '@astrojs/markdown-remark'
|
|
10
|
+
import { headingAnchors } from '../scripts/localization'
|
|
11
|
+
import { isSharedMdxSample } from '../scripts/mdx-sample'
|
|
12
|
+
import { translateShell } from '../docs-shell/common/translations'
|
|
9
13
|
import { generatePresetCSS } from '@master/internal-site/css/generate-preset-css.ts'
|
|
10
14
|
import { selectedSpecimensMarkdown } from '@master/internal-site/css/foundation-data/specimen-content.ts'
|
|
11
15
|
import { getVariableNamespacePublicKeys } from '@master/internal-site/css/manifest-utilities.ts'
|
|
@@ -33,7 +37,7 @@ export function syntaxMarkdown(rows: SyntaxRow[]) {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export function portableMarkdown(markdown: string) {
|
|
36
|
-
return markdown.split(/(```[\s\S]*?```)/g).map(part => part.startsWith('```') ? part : part.replace(/<!-- \/?reference-illustration(?::[\w-]+)? -->\n*/g, '').replace(/^(#{2,
|
|
40
|
+
return markdown.split(/(```[\s\S]*?```)/g).map(part => part.startsWith('```') ? part : part.replace(/<!-- \/?reference-illustration(?::[\w-]+)? -->\n*/g, '').replace(/^(#{2,6}) (.+) \{#([\w-]+)\}$/gm, '<a id="$3"></a>\n\n$1 $2')).join('')
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
/** Resolve authored literals only. Never execute MDX expressions to extract documents. */
|
|
@@ -50,9 +54,11 @@ function literal(node: any, variables: Record<string, unknown>): unknown {
|
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
export interface MdxContentOptions {
|
|
57
|
+
/** Propagates through nested MDX includes and custom text adapters. */
|
|
58
|
+
locale?: string
|
|
53
59
|
/** Reference Overview renders syntax rows; Guide Overview may be a local MDX include. */
|
|
54
60
|
overview?: 'syntax' | 'include'
|
|
55
|
-
component?: (name: string, attributes: Record<string, any>, file: string, context: { expression: (source: string) => Promise<unknown
|
|
61
|
+
component?: (name: string, attributes: Record<string, any>, file: string, context: { expression: (source: string) => Promise<unknown>; locale: string }) => string | undefined | Promise<string | undefined>
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
/**
|
|
@@ -64,7 +70,18 @@ const expressionElement = /(<(Code|Class2CSS|DocumentDeclaration)\b(?:"[^"]*"|'[
|
|
|
64
70
|
export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [], stack: string[] = [], options: MdxContentOptions = {}) {
|
|
65
71
|
if (stack.includes(file)) throw new Error(`Recursive document include: ${file}`)
|
|
66
72
|
const expressions: Record<string, string> = {}
|
|
67
|
-
const
|
|
73
|
+
const locale = options.locale ?? file.match(/\.(tw|ja|ko|cn)\.mdx$/)?.[1] ?? 'en'
|
|
74
|
+
const t = (text: string) => translateShell(locale, text)
|
|
75
|
+
options = { ...options, locale }
|
|
76
|
+
const original = file.replace(/\.(tw|ja|ko|cn)\.mdx$/, '.mdx')
|
|
77
|
+
const canonical = parseFrontmatter(await readFile(original, 'utf8'))
|
|
78
|
+
if (canonical.frontmatter.draft === true || canonical.frontmatter.disabled === true) throw new Error(`Unpublished source MDX document: ${original}`)
|
|
79
|
+
const document = original === file ? canonical : parseFrontmatter(await readFile(file, 'utf8'))
|
|
80
|
+
if (document.frontmatter.draft === true || document.frontmatter.disabled === true) throw new Error(`Unpublished translated MDX document: ${file}`)
|
|
81
|
+
const source = document.content.split(/(```[\s\S]*?```)/g).map(part => part.startsWith('```') ? part : part.replace(/\{?<Demo\b[\s\S]*?<\/Demo>\}?/g, '').replace(expressionElement, (_, start, _name, expression, end) => { const key = `MCSS_EXPRESSION_${Object.keys(expressions).length}`; expressions[key] = expression; return `${start}\n${key}\n${end}` })).join('')
|
|
82
|
+
let sourceAnchors: string[]
|
|
83
|
+
try { sourceAnchors = headingAnchors(source) } catch (error) { throw new Error(`Cannot read headings in ${file}`, { cause: error }) }
|
|
84
|
+
const headingIds = new Map<any, string>()
|
|
68
85
|
const examples: ReferenceExample[] = []
|
|
69
86
|
const notes: string[] = []
|
|
70
87
|
const variables: Record<string, unknown> = {}
|
|
@@ -75,6 +92,12 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
75
92
|
extensions: [{ disable: { null: ['htmlFlow', 'htmlText', 'codeIndented'] } }, mdxjsEsm({ acorn, addResult: true }), mdxJsx({ acorn, addResult: true })],
|
|
76
93
|
mdastExtensions: [mdxjsEsmFromMarkdown(), mdxJsxFromMarkdown()]
|
|
77
94
|
}) } catch (error) { throw new Error(`Cannot parse ${file}`, { cause: error }) }
|
|
95
|
+
let headingIndex = 0
|
|
96
|
+
const collectHeadingIds = (node: any) => {
|
|
97
|
+
if (node.type === 'heading' && node.depth >= 2 && node.depth <= 6) headingIds.set(node, sourceAnchors[headingIndex++])
|
|
98
|
+
node.children?.forEach(collectHeadingIds)
|
|
99
|
+
}
|
|
100
|
+
collectHeadingIds(tree)
|
|
78
101
|
const raw = (node: any) => source.slice(node.position.start.offset, node.position.end.offset)
|
|
79
102
|
const collectEsm = (node: any) => {
|
|
80
103
|
if (node.type === 'mdxjsEsm') {
|
|
@@ -135,7 +158,7 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
135
158
|
const name = node.name ?? ''
|
|
136
159
|
const attrs: Record<string, any> = Object.fromEntries((node.attributes ?? []).filter((a: any) => a.name).map((a: any) => [a.name, a.value]))
|
|
137
160
|
const inner = (node.children ?? []).map(raw).join('\n')
|
|
138
|
-
const adapted = await options.component?.(name, attrs, file, { expression })
|
|
161
|
+
const adapted = await options.component?.(name, attrs, file, { expression, locale })
|
|
139
162
|
if (adapted !== undefined) return adapted
|
|
140
163
|
const attribute = (value: any) => value?.type === 'mdxJsxAttributeValueExpression' ? expression(value.value) : value
|
|
141
164
|
if (name === 'DocumentPrompt') {
|
|
@@ -148,10 +171,11 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
148
171
|
const result = await attribute(attrs.result)
|
|
149
172
|
const diagnostic = await attribute(attrs.diagnostic)
|
|
150
173
|
if (typeof source !== 'string' || typeof attrs.language !== 'string') throw new Error('DocumentCodeExample requires literal source and language')
|
|
151
|
-
const
|
|
174
|
+
const sourceLabel = attrs.sourceLabel ?? (result !== undefined && attrs.resultKind !== 'generated-css' ? t('Source') : undefined)
|
|
175
|
+
const parts = [`**${attrs.title}**`, ...(sourceLabel ? [`**${sourceLabel}**`] : []), `\`\`\`${attrs.language}\n${source}\n\`\`\``]
|
|
152
176
|
if (result !== undefined) {
|
|
153
177
|
if (typeof result !== 'string') throw new Error('DocumentCodeExample requires a literal result')
|
|
154
|
-
parts.push(`**${attrs.resultLabel ?? (attrs.resultKind === 'generated-css' ? 'Generated CSS' : 'Result')}**`, `\`\`\`${attrs.resultLanguage ?? attrs.language}\n${result}\n\`\`\``)
|
|
178
|
+
parts.push(`**${attrs.resultLabel ?? t(attrs.resultKind === 'generated-css' ? 'Generated CSS' : 'Result')}**`, `\`\`\`${attrs.resultLanguage ?? attrs.language}\n${result}\n\`\`\``)
|
|
155
179
|
}
|
|
156
180
|
if (diagnostic) parts.push(`${diagnostic.severity} (\`${diagnostic.rule}\`): ${diagnostic.message}`)
|
|
157
181
|
return parts.join('\n\n')
|
|
@@ -159,7 +183,7 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
159
183
|
if (['DocumentOptions', 'DocumentParameters'].includes(name)) {
|
|
160
184
|
const values = await expression(attrs[name === 'DocumentOptions' ? 'options' : 'parameters'].value) as { name: string, type?: string, requirement?: string, defaultValue?: string, description: string }[]
|
|
161
185
|
if (!Array.isArray(values) || values.some(value => typeof value.name !== 'string' || typeof value.description !== 'string')) throw new Error(`${name} requires literal names and descriptions`)
|
|
162
|
-
return values.map(value => `**\`${value.name}\`**${value.type ? ` — \`${value.type}\`` : ''}${value.requirement ? ` (${value.requirement})` : ''}\n\n${value.defaultValue !== undefined ?
|
|
186
|
+
return values.map(value => `**\`${value.name}\`**${value.type ? ` — \`${value.type}\`` : ''}${value.requirement ? ` (${value.requirement})` : ''}\n\n${value.defaultValue !== undefined ? `${t('Default')}: \`${value.defaultValue}\`. ` : ''}${value.description}`).join('\n\n')
|
|
163
187
|
}
|
|
164
188
|
if (name === 'DocumentAPIIndex') {
|
|
165
189
|
const values = await expression(attrs.entries.value) as { name: string, href: string, description: string }[]
|
|
@@ -169,17 +193,25 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
169
193
|
if (name === 'DocumentDeclaration') return `**${attrs.label}**\n\n\`\`\`typescript\n${await expression(inner)}\n\`\`\``
|
|
170
194
|
if (name === 'DocumentValueList') {
|
|
171
195
|
const values = await expression(attrs.rows.value) as { id: string, title: string, identifier?: string, values: { label: string, value: string }[] }[]
|
|
172
|
-
|
|
196
|
+
const headingLevel = await attribute(attrs.headingLevel) ?? 3
|
|
197
|
+
if (headingLevel !== 3 && headingLevel !== 4) throw new Error('DocumentValueList requires headingLevel 3 or 4')
|
|
198
|
+
return values.map(value => `${'#'.repeat(headingLevel)} ${value.title} {#${value.id}}\n\n${value.identifier ? `\`${value.identifier}\`\n\n` : ''}${value.values.map(pair => `${pair.label}: \`${pair.value}\``).join('\n\n')}`).join('\n\n')
|
|
199
|
+
}
|
|
200
|
+
if (name === 'DocumentCodeTable') {
|
|
201
|
+
const rows = await expression(attrs.rows.value) as { syntax: string, css: string }[]
|
|
202
|
+
if (!Array.isArray(rows) || rows.some(row => typeof row.syntax !== 'string' || typeof row.css !== 'string')) throw new Error('DocumentCodeTable requires literal syntax and CSS rows')
|
|
203
|
+
const code = (value: string) => `\`${value.replaceAll('|', '\\|')}\``
|
|
204
|
+
return `| ${attrs.label ?? t('Syntax')} | CSS |\n| --- | --- |\n${rows.map(row => `| ${code(row.syntax)} | ${code(row.css)} |`).join('\n')}`
|
|
173
205
|
}
|
|
174
206
|
if (name === 'DocumentFlow') {
|
|
175
207
|
const steps = await expression(attrs.steps.value) as { title: string, description: string }[]
|
|
176
208
|
return `**${attrs.title}**\n\n${steps.map((step, index) => `${index + 1}. **${step.title}** — ${step.description}`).join('\n')}${attrs.caption ? `\n\n${attrs.caption}` : ''}`
|
|
177
209
|
}
|
|
178
|
-
if (name === 'DocumentFileTree') {
|
|
210
|
+
if (name === 'DocumentFileTree' || name === 'ExplorerView') {
|
|
179
211
|
type Entry = { name: string, description?: string, children?: Entry[] }
|
|
180
|
-
const entries = await expression(attrs
|
|
212
|
+
const entries = await expression(attrs[name === 'ExplorerView' ? 'items' : 'entries'].value) as Entry[]
|
|
181
213
|
const lines = (items: Entry[], level = 0): string => items.map(item => `${' '.repeat(level)}- \`${item.name}${item.children ? '/' : ''}\`${item.description ? ` — ${item.description}` : ''}${item.children?.length ? `\n${lines(item.children, level + 1)}` : ''}`).join('\n')
|
|
182
|
-
return `**${attrs.title}**\n\n${lines(entries)}${attrs.caption ? `\n\n${attrs.caption}` : ''}`
|
|
214
|
+
return `${attrs.title ? `**${attrs.title}**\n\n` : ''}${lines(entries)}${attrs.caption ? `\n\n${attrs.caption}` : ''}`
|
|
183
215
|
}
|
|
184
216
|
if (name === 'Overview' && options.overview !== 'include') return syntaxMarkdown(rows)
|
|
185
217
|
if (name === 'StylesheetExample') {
|
|
@@ -187,7 +219,7 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
187
219
|
if (typeof attrs.title !== 'string' || typeof source !== 'string') throw new Error('StylesheetExample requires a literal title and source')
|
|
188
220
|
return stylesheetExampleMarkdown(attrs.title, source)
|
|
189
221
|
}
|
|
190
|
-
if (name === 'FoundationTokens') return selectedSpecimensMarkdown(attrs.namespace, await expression(attrs.keys.value) as string[])
|
|
222
|
+
if (name === 'FoundationTokens') return selectedSpecimensMarkdown(attrs.namespace, await expression(attrs.keys.value) as string[], t)
|
|
191
223
|
if (name === 'DemoPageViewport') return `[Open the resizable ${attrs.title} example](${attrs.src}). The viewport slider also supports arrow keys.`
|
|
192
224
|
if (name === 'DemoConfiguredExample') {
|
|
193
225
|
const configuration = typeof attrs.source === 'string' ? attrs.source : await expression(attrs.source.value) as string
|
|
@@ -246,9 +278,20 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
246
278
|
if (/^[A-Z]/.test(name)) {
|
|
247
279
|
const imported = imports[name]
|
|
248
280
|
const siteRoot = file.slice(0, file.lastIndexOf('/content/'))
|
|
249
|
-
|
|
281
|
+
let target = imported?.startsWith('~/site/') ? path.join(siteRoot, imported.slice(7))
|
|
250
282
|
: imported?.startsWith('.') ? path.resolve(path.dirname(file), imported)
|
|
251
283
|
: path.join(path.dirname(file), 'components', `${name}.mdx`)
|
|
284
|
+
target = target.replace(/\.(tw|ja|ko|cn)\.mdx$/, '.mdx')
|
|
285
|
+
if (target.endsWith('.mdx') && locale !== 'en') {
|
|
286
|
+
const original = await readFile(target, 'utf8').catch(() => '')
|
|
287
|
+
const metadata = parseFrontmatter(original).frontmatter
|
|
288
|
+
if (metadata.draft === true || metadata.disabled === true) throw new Error(`Unpublished source MDX document: ${target}`)
|
|
289
|
+
if (original.trim() && !isSharedMdxSample(target, original)) {
|
|
290
|
+
const translated = target.replace(/\.mdx$/, `.${locale}.mdx`)
|
|
291
|
+
if (await access(translated).then(() => true, () => false)) target = translated
|
|
292
|
+
else throw new Error(`Missing translated MDX include: ${translated}`)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
252
295
|
if (target.endsWith('.mdx') && await access(target).then(() => true, () => false)) {
|
|
253
296
|
const result = await extractReferenceMdx(target, rows, [...stack, file], options)
|
|
254
297
|
examples.push(...result.examples)
|
|
@@ -268,7 +311,14 @@ export async function extractReferenceMdx(file: string, rows: SyntaxRow[] = [],
|
|
|
268
311
|
const end = child.position.end.offset - node.position.start.offset
|
|
269
312
|
text = text.slice(0, start) + await render(child) + text.slice(end)
|
|
270
313
|
}
|
|
271
|
-
|
|
314
|
+
if (node.type === 'heading') {
|
|
315
|
+
text = text.replace(/\\([{}])/g, '$1')
|
|
316
|
+
if (node.depth >= 2 && node.depth <= 6) {
|
|
317
|
+
const id = headingIds.get(node)
|
|
318
|
+
if (!/\s+\{#[\w-]+\}\s*$/.test(text)) text = text.replace(/\s+#+\s*$/, '') + ` {#${id}}`
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return text
|
|
272
322
|
}
|
|
273
323
|
const parts: string[] = []
|
|
274
324
|
for (const child of tree.children) parts.push(await render(child))
|
package/src/demo/Demo.svelte
CHANGED
|
@@ -30,8 +30,13 @@
|
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
32
|
<script lang="ts">
|
|
33
|
+
import '@master/internal-site/styles/system/stage.css'
|
|
34
|
+
import '@master/internal-site/styles/system/tray.css'
|
|
35
|
+
import '@master/internal-site/styles/system/tray-code.css'
|
|
36
|
+
|
|
33
37
|
import '@master/internal-site/styles/demo.css'
|
|
34
38
|
import { styleText } from './style'
|
|
39
|
+
import { getSite } from '@master/internal-site/site'
|
|
35
40
|
|
|
36
41
|
/** One example is one tray: head, stage, source, caption. class and style belong to the stage; the chrome never joins the demonstrated layout. */
|
|
37
42
|
let {
|
|
@@ -39,17 +44,18 @@
|
|
|
39
44
|
frameClassName, class: className, style, children, ...props
|
|
40
45
|
}: DemoProps = $props()
|
|
41
46
|
const head = $derived(Boolean(title || description || controls))
|
|
47
|
+
const { t } = getSite()
|
|
42
48
|
</script>
|
|
43
49
|
|
|
44
|
-
{#snippet node(value: DemoNode)}{#if typeof value === 'function'}{@render value()}{:else}{value}{/if}{/snippet}
|
|
50
|
+
{#snippet node(value: DemoNode, translate = false)}{#if typeof value === 'function'}{@render value()}{:else}{translate ? t(value) : value}{/if}{/snippet}
|
|
45
51
|
|
|
46
52
|
<figure {...props} class={['ui-tray', frameClassName]}>{#if head}<figcaption class="ui-tray-head">
|
|
47
53
|
{#if title || description}<div>
|
|
48
|
-
{#if title}<p class="ui-tray-title">{title}</p>{/if}
|
|
49
|
-
{#if description}<p class="ui-tray-description">{@render node(description)}</p>{/if}
|
|
54
|
+
{#if title}<p class="ui-tray-title">{t(title)}</p>{/if}
|
|
55
|
+
{#if description}<p class="ui-tray-description">{@render node(description, true)}</p>{/if}
|
|
50
56
|
</div>{/if}
|
|
51
57
|
{#if controls}<div class="ui-tray-tools">{@render node(controls)}</div>{/if}
|
|
52
58
|
</figcaption>{/if}{#if frame === 'none'}{@render children?.()}{:else}<div class={['ui-stage', className]} style={styleText(style)}
|
|
53
59
|
data-background={background === 'plain' ? undefined : background}
|
|
54
60
|
data-padding={padding === 'lg' ? undefined : padding}
|
|
55
|
-
data-align={align === 'center' ? undefined : align}>{@render children?.()}</div>{/if}{#if source}{@render node(source)}{/if}{#if caption}{#if head}<div class="ui-tray-caption">{@render node(caption)}</div>{:else}<figcaption class="ui-tray-caption">{@render node(caption)}</figcaption>{/if}{/if}</figure>
|
|
61
|
+
data-align={align === 'center' ? undefined : align}>{@render children?.()}</div>{/if}{#if source}{@render node(source)}{/if}{#if caption}{#if head}<div class="ui-tray-caption">{@render node(caption, true)}</div>{:else}<figcaption class="ui-tray-caption">{@render node(caption, true)}</figcaption>{/if}{/if}</figure>
|
package/src/demo/DemoAsset.astro
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
+
import '@master/internal-site/styles/interface.css'
|
|
2
3
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
4
|
import IconDownload from '@tabler/icons-svelte-runes/icons/download'
|
|
4
5
|
import Demo from './Demo.svelte'
|
|
5
6
|
import Image from '@master/internal-site/components/Image.svelte'
|
|
7
|
+
import { siteOf } from '../astro/site-context'
|
|
6
8
|
|
|
7
9
|
export interface DemoAssetProps {
|
|
8
10
|
title: string
|
|
@@ -22,17 +24,18 @@ type Props = DemoAssetProps
|
|
|
22
24
|
* transparent artwork sits on a checkerboard. A demo container keeps the prose media perimeter off the artwork.
|
|
23
25
|
*/
|
|
24
26
|
const { title, description, src, alt, width, height, format = 'SVG', surface = 'transparent' } = Astro.props
|
|
27
|
+
const { t } = siteOf(Astro)
|
|
25
28
|
---
|
|
26
29
|
|
|
27
30
|
<Demo title={title} description={description} background={surface === 'transparent' ? 'checkerboard' : 'plain'} class={surface === 'transparent' ? undefined : surface} data-asset={surface}>
|
|
28
31
|
<Fragment slot="caption">
|
|
29
32
|
<span class="flex flex-wrap items-center justify-between gap-sm">
|
|
30
33
|
<span class="ui-badge" data-size="sm">{format}</span>
|
|
31
|
-
<a href={src} download class="ui-button" data-size="sm" aria-label={
|
|
34
|
+
<a href={src} download class="ui-button" data-size="sm" aria-label={t('Download {title} ({format})').replace('{title}', t(title)).replace('{format}', format)}>
|
|
32
35
|
<IconDownload aria-hidden="true" />
|
|
33
|
-
Download {format}
|
|
36
|
+
{t('Download {format}').replace('{format}', format)}
|
|
34
37
|
</a>
|
|
35
38
|
</span>
|
|
36
39
|
</Fragment>
|
|
37
|
-
<div class="grid (place-items:center) w-full" data-demo-container=""><Image src={src} alt={alt} width={width} height={height} class="block h-auto w-auto max-w-full (max-height:var(--spacing-4xl))" /></div>
|
|
40
|
+
<div class="grid (place-items:center) w-full" data-demo-container=""><Image src={src} alt={t(alt)} width={width} height={height} class="block h-auto w-auto max-w-full (max-height:var(--spacing-4xl))" /></div>
|
|
38
41
|
</Demo>
|
package/src/demo/DemoAxes.svelte
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
5
|
import type { Snippet } from 'svelte'
|
|
4
6
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
5
7
|
import { styleText, type DemoStyle } from '@master/internal-site/demo/style.ts'
|
|
6
8
|
|
|
7
9
|
/** `inline` and `block` take text, or a snippet (a named slot from `.astro` and `.mdx`). */
|
|
8
|
-
let { inline = 'Main axis', block = 'Cross axis', children, class: className, style, ...props }: Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {
|
|
10
|
+
let { inline = t('Main axis'), block = t('Cross axis'), children, class: className, style, ...props }: Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {
|
|
9
11
|
inline?: string | Snippet
|
|
10
12
|
block?: string | Snippet
|
|
11
13
|
style?: DemoStyle
|
|
@@ -13,7 +15,7 @@
|
|
|
13
15
|
} = $props()
|
|
14
16
|
</script>
|
|
15
17
|
|
|
16
|
-
{#snippet node(value: string | Snippet)}{#if typeof value === 'function'}{@render value()}{:else}{value}{/if}{/snippet}
|
|
18
|
+
{#snippet node(value: string | Snippet)}{#if typeof value === 'function'}{@render value()}{:else}{t(value)}{/if}{/snippet}
|
|
17
19
|
|
|
18
20
|
<div {...props} class={['ui-axes', className]} style={styleText(style)}>
|
|
19
21
|
<div class="ui-axes-inline"><span>{@render node(inline)}</span><span class="ui-axes-rule" aria-hidden="true"></span></div>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { siteOf } from '@master/internal-site/astro/site-context.ts'
|
|
3
|
+
const { t } = siteOf(Astro)
|
|
4
|
+
import '@master/internal-site/styles/system/disclosure.css'
|
|
2
5
|
import '@master/internal-site/styles/demo.css'
|
|
3
6
|
import RenderNode from '@master/internal-site/components/RenderNode.astro'
|
|
4
7
|
import DemoIndex from '@master/internal-site/demo/DemoIndex.astro'
|
|
@@ -19,16 +22,16 @@ const { groups } = Astro.props
|
|
|
19
22
|
---
|
|
20
23
|
|
|
21
24
|
<div class="ui-catalog">
|
|
22
|
-
<DemoIndex label=
|
|
23
|
-
title: 'Choose a behavior',
|
|
24
|
-
links: groups.map(group => ({ href: `#${group.id}`, label: `${group.title} · ${group.entries.length}` }))
|
|
25
|
+
<DemoIndex label={t('Utility recipe categories')} groups={[{
|
|
26
|
+
title: t('Choose a behavior'),
|
|
27
|
+
links: groups.map(group => ({ href: `#${group.id}`, label: `${t(group.title)} · ${group.entries.length}` }))
|
|
25
28
|
}]} />
|
|
26
29
|
{groups.map(group => <section aria-labelledby={group.id}>
|
|
27
|
-
<h3 id={group.id}>{group.title}<small>{group.entries.length}
|
|
30
|
+
<h3 id={group.id}>{t(group.title)}<small>{t('{count} recipes').replace('{count}', String(group.entries.length))}</small></h3>
|
|
28
31
|
{group.entries.map(entry => <details class="ui-disclosure" data-variant="rule">
|
|
29
|
-
<summary>{entry.title}<span class="ui-disclosure-meta">{entry.label}</span></summary>
|
|
32
|
+
<summary>{t(entry.title)}<span class="ui-disclosure-meta">{t(entry.label)}</span></summary>
|
|
30
33
|
<div class="ui-catalog-entry">
|
|
31
|
-
{entry.href && <a href={entry.href}>Read related documentation ↗</a>}
|
|
34
|
+
{entry.href && <a href={entry.href}>{t('Read related documentation')} ↗</a>}
|
|
32
35
|
<RenderNode node={entry.children} />
|
|
33
36
|
</div>
|
|
34
37
|
</details>)}
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<script lang="ts">
|
|
13
|
+
import '@master/internal-site/styles/system/compare.css'
|
|
14
|
+
import '@master/internal-site/styles/system/stage.css'
|
|
15
|
+
|
|
13
16
|
import '@master/internal-site/styles/system/specimens.css'
|
|
14
17
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
15
18
|
import { styleText, type DemoStyle } from '@master/internal-site/demo/style.ts'
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
4
|
+
import '@master/internal-site/styles/interface.css'
|
|
5
|
+
import '@master/internal-site/styles/system/range.css'
|
|
6
|
+
|
|
2
7
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
8
|
import type { Snippet } from 'svelte'
|
|
4
9
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
@@ -35,12 +40,12 @@
|
|
|
35
40
|
</script>
|
|
36
41
|
|
|
37
42
|
{#snippet controls()}
|
|
38
|
-
<label class="ui-label" data-case="as-is" for={id}>Container</label>
|
|
43
|
+
<label class="ui-label" data-case="as-is" for={id}>{t('Container')}</label>
|
|
39
44
|
<input {id} class="ui-range" type="range" min={minimumWidth} max={maxWidth} step="1" disabled={!ready} {value}
|
|
40
45
|
style:--value={`${((value - minimumWidth) / range) * 100}%`} style:width="128px" style:max-width="100%"
|
|
41
46
|
oninput={event => { width = Number(event.currentTarget.value) }} />
|
|
42
|
-
<button type="button" class="ui-button" data-size="sm" disabled={!ready} onclick={() => { width = undefined }}>Fit</button>
|
|
43
|
-
<output class="ui-label" data-case="as-is">{ready ?
|
|
47
|
+
<button type="button" class="ui-button" data-size="sm" disabled={!ready} onclick={() => { width = undefined }}>{t('Fit')}</button>
|
|
48
|
+
<output class="ui-label" data-case="as-is">{ready ? t('{width} px · viewport unchanged').replace('{width}', String(measured)) : t('Measuring container…')}</output>
|
|
44
49
|
{/snippet}
|
|
45
50
|
|
|
46
51
|
<Demo {...props} {title} {caption} padding="sm" data-ready={ready} {controls}>
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
4
|
+
import '@master/internal-site/styles/system/segmented.css'
|
|
5
|
+
|
|
2
6
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
7
|
import type { Snippet } from 'svelte'
|
|
4
8
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
@@ -13,4 +17,4 @@
|
|
|
13
17
|
} = $props()
|
|
14
18
|
</script>
|
|
15
19
|
|
|
16
|
-
<div {...props} role="group" aria-label={label} class={[variant === 'segmented' ? 'ui-segmented' : 'flex flex-wrap items-center gap-xs', className]} style={styleText(style)}>{@render children?.()}</div>
|
|
20
|
+
<div {...props} role="group" aria-label={t(label)} class={[variant === 'segmented' ? 'ui-segmented' : 'flex flex-wrap items-center gap-xs', className]} style={styleText(style)}>{@render children?.()}</div>
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
4
|
+
import '@master/internal-site/styles/interface.css'
|
|
5
|
+
import '@master/internal-site/styles/system/copy.css'
|
|
6
|
+
|
|
2
7
|
import type { Snippet } from 'svelte'
|
|
3
8
|
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
4
9
|
import IconCopy from '@tabler/icons-svelte-runes/icons/copy'
|
|
@@ -25,19 +30,19 @@
|
|
|
25
30
|
async function copy() {
|
|
26
31
|
if (busy) return
|
|
27
32
|
busy = true
|
|
28
|
-
report('Copying…', undefined)
|
|
33
|
+
report(t('Copying…'), undefined)
|
|
29
34
|
try {
|
|
30
35
|
if (!window.isSecureContext || !navigator.clipboard?.writeText) throw new Error('Clipboard unavailable')
|
|
31
36
|
await navigator.clipboard.writeText(value)
|
|
32
|
-
report(feedback === 'compact' ? 'Copied' :
|
|
37
|
+
report(feedback === 'compact' ? t('Copied') : t('Copied {value}').replace('{value}', value), 'success')
|
|
33
38
|
} catch {
|
|
34
|
-
report(feedback === 'compact' ? 'Copy unavailable' :
|
|
39
|
+
report(feedback === 'compact' ? t('Copy unavailable') : t('Copy unavailable: {value}').replace('{value}', value), 'error')
|
|
35
40
|
} finally { busy = false }
|
|
36
41
|
}
|
|
37
42
|
</script>
|
|
38
43
|
|
|
39
44
|
{#snippet button()}
|
|
40
|
-
<button data-size={className ? undefined : 'sm'} {...props} type="button" aria-label={label} class={className ?? 'ui-button'} style={styleText(style)} aria-busy={busy} onclick={copy}>
|
|
45
|
+
<button data-size={className ? undefined : 'sm'} {...props} type="button" aria-label={t(label)} class={className ?? 'ui-button'} style={styleText(style)} aria-busy={busy} onclick={copy}>
|
|
41
46
|
{#if icon === undefined}<IconCopy aria-hidden="true" />{:else if icon}{@render icon()}{/if}{@render children?.()}
|
|
42
47
|
</button>
|
|
43
48
|
{/snippet}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
4
|
+
import '@master/internal-site/styles/system/copy.css'
|
|
5
|
+
|
|
2
6
|
import type { Snippet } from 'svelte'
|
|
3
7
|
import { setCopyFeedback, type CopyResult } from '@master/internal-site/demo/copy-feedback.ts'
|
|
4
8
|
|
|
5
9
|
/** One status for a set of copy actions, such as a palette. The buttons must render in this group's Svelte tree. */
|
|
6
|
-
let { children, instruction = 'Select a swatch to copy its variable.' }: { children?: Snippet, instruction?: string } = $props()
|
|
10
|
+
let { children, instruction = t('Select a swatch to copy its variable.') }: { children?: Snippet, instruction?: string } = $props()
|
|
7
11
|
let state = $state<{ instruction: string, message: string, result: CopyResult }>()
|
|
8
12
|
const current = $derived(state?.instruction === instruction ? state : undefined)
|
|
9
13
|
setCopyFeedback((message, result) => { state = { instruction, message, result } })
|
|
10
14
|
</script>
|
|
11
15
|
|
|
12
16
|
<div class="grid gap-sm">
|
|
13
|
-
<p class="m(0) ui-copy"><span class="ui-copy-status" role="status" data-result={current?.result}>{current?.message ?? instruction}</span></p>
|
|
17
|
+
<p class="m(0) ui-copy"><span class="ui-copy-status" role="status" data-result={current?.result}>{current?.message ?? t(instruction)}</span></p>
|
|
14
18
|
{@render children?.()}
|
|
15
19
|
</div>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { siteOf } from '@master/internal-site/astro/site-context.ts'
|
|
3
|
+
const { t } = siteOf(Astro)
|
|
2
4
|
import Demo from '@master/internal-site/demo/Demo.svelte'
|
|
3
5
|
import DemoViewport from '@master/internal-site/demo/DemoViewport.svelte'
|
|
4
6
|
import { referenceDemoSections } from '@master/internal-site/demo/reference/source.ts'
|
|
@@ -22,6 +24,6 @@ const printable = source.classes.some(value => value.includes('@media(print)'))
|
|
|
22
24
|
---
|
|
23
25
|
|
|
24
26
|
<Demo title={source.title} frame="none" caption={scene.caption} data-demo-case={`${page}#${section}`}>
|
|
25
|
-
<DemoViewport client:idle={{ timeout: 500 }} title={`${page}: ${source.title}`} document={demoDocument(source, scene)} responsive={scene.responsive ?? responsive}
|
|
27
|
+
<DemoViewport client:idle={{ timeout: 500 }} title={`${page}: ${t(source.title)}`} document={demoDocument(source, scene)} responsive={scene.responsive ?? responsive}
|
|
26
28
|
theme={scene.theme ?? themed} print={printable} motion={scene.motion} inspect={scene.inspect ?? (section === 'apply-conditionally' ? [page] : undefined)} height={scene.height} maxWidth={scene.maxWidth} sizing={scene.sizing} />
|
|
27
29
|
</Demo>
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import '@master/internal-site/styles/system/inline-code.css'
|
|
3
|
+
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
5
|
+
import { getSite } from '@master/internal-site/site'
|
|
6
|
+
const { t } = getSite()
|
|
3
7
|
import { onMount } from 'svelte'
|
|
4
8
|
|
|
5
9
|
/** Reports syntax support only; the example still owns its native CSS behavior. */
|
|
@@ -13,6 +17,6 @@
|
|
|
13
17
|
<p class="flex flex-wrap items-center gap-xs m(0)" data-supported={supported ?? 'unknown'}>
|
|
14
18
|
<code class="ui-inline-code">{condition}</code>
|
|
15
19
|
<span class="ui-badge" data-variant="dot" data-tone={supported ? 'green' : undefined}>
|
|
16
|
-
{supported === null ? 'Checking…' : supported ? 'Supported' : 'Not supported'}
|
|
20
|
+
{supported === null ? t('Checking…') : supported ? t('Supported') : t('Not supported')}
|
|
17
21
|
</span>
|
|
18
22
|
</p>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import '@master/internal-site/styles/system/disclosure.css'
|
|
3
|
+
|
|
2
4
|
import type { Snippet } from 'svelte'
|
|
5
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
6
|
|
|
4
7
|
/** The complete generated stylesheet stays one native, closed disclosure under the source. */
|
|
5
8
|
let { children }: { children?: Snippet } = $props()
|
|
9
|
+
const { t } = getSite()
|
|
6
10
|
</script>
|
|
7
11
|
|
|
8
|
-
<details class="ui-disclosure"><summary>Generated CSS</summary>{@render children?.()}</details>
|
|
12
|
+
<details class="ui-disclosure"><summary>{t('Generated CSS')}</summary>{@render children?.()}</details>
|
package/src/demo/DemoIndex.astro
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { siteOf } from '@master/internal-site/astro/site-context.ts'
|
|
3
|
+
const { t } = siteOf(Astro)
|
|
4
|
+
import '@master/internal-site/styles/interface.css'
|
|
2
5
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
6
|
|
|
4
7
|
export interface DemoIndexGroup {
|
|
@@ -15,9 +18,9 @@ interface Props {
|
|
|
15
18
|
const { label, groups } = Astro.props
|
|
16
19
|
---
|
|
17
20
|
|
|
18
|
-
<nav class="grid gap-md" aria-label={label}>
|
|
21
|
+
<nav class="grid gap-md" aria-label={t(label)}>
|
|
19
22
|
{groups.map(group => <div class="grid gap-xs">
|
|
20
|
-
<p class="m(0) ui-label">{group.title}</p>
|
|
21
|
-
<ul class="flex flex-wrap gap-2xs m(0) p(0) (list-style:none)">{group.links.map(link => <li><a class="ui-button" data-size="sm" href={link.href}>{link.label}</a></li>)}</ul>
|
|
23
|
+
<p class="m(0) ui-label">{t(group.title)}</p>
|
|
24
|
+
<ul class="flex flex-wrap gap-2xs m(0) p(0) (list-style:none)">{group.links.map(link => <li><a class="ui-button" data-size="sm" href={link.href}>{t(link.label)}</a></li>)}</ul>
|
|
22
25
|
</div>)}
|
|
23
26
|
</nav>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
5
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
4
6
|
import { styleText, type DemoStyle } from '@master/internal-site/demo/style.ts'
|
|
@@ -10,6 +12,6 @@
|
|
|
10
12
|
} = $props()
|
|
11
13
|
</script>
|
|
12
14
|
|
|
13
|
-
<ul {...props} class={['ui-legend', className]} style={styleText(style)} aria-label=
|
|
15
|
+
<ul {...props} class={['ui-legend', className]} style={styleText(style)} aria-label={t('Legend')}>
|
|
14
16
|
{#each items as { label, tone: value } (label)}<li><i data-tone={tone(value)} aria-hidden="true"></i>{label}</li>{/each}
|
|
15
17
|
</ul>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
5
|
import type { Snippet } from 'svelte'
|
|
4
6
|
|
|
@@ -20,8 +22,8 @@
|
|
|
20
22
|
|
|
21
23
|
<div class="ui-measure">
|
|
22
24
|
<div class="ui-measure-head">
|
|
23
|
-
<span>{label}</span>
|
|
24
|
-
<output aria-label={
|
|
25
|
+
<span>{t(label)}</span>
|
|
26
|
+
<output aria-label={t('{label} dimensions').replace('{label}', t(label))}>{size ? `${size.width} × ${size.height} px` : t('Measuring…')}</output>
|
|
25
27
|
</div>
|
|
26
28
|
<div class="ui-measure-rule" aria-hidden="true"></div>
|
|
27
29
|
<div bind:this={element}>{@render children?.()}</div>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
5
|
import type { ClassValue } from 'svelte/elements'
|
|
4
6
|
import type { SVGAttributes } from 'svelte/elements'
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
{@const imageProps: SiteImageProps = { width: 320, height: 200, ...(props as Omit<ImageProps, 'src' | 'alt' | 'style'>), style: styleText(style), src, alt: alt! }}
|
|
28
30
|
<Image {...imageProps} />
|
|
29
31
|
{:else}
|
|
30
|
-
<svg viewBox="0 0 320 200" role="img" aria-label=
|
|
32
|
+
<svg viewBox="0 0 320 200" role="img" aria-label={t('Sun above two mountain ridges')} {...props as SVGAttributes<SVGSVGElement>}
|
|
31
33
|
style={[`color:var(--ui-tone-${value})`, styleText(style)].filter(Boolean).join(';')}>
|
|
32
34
|
<rect width="320" height="200" fill="var(--ui-surface-sheet)" />
|
|
33
35
|
<path d="M0 175V158l92-93 113 110H0Z" fill="currentColor" opacity=".1" />
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
4
|
+
import '@master/internal-site/styles/interface.css'
|
|
2
5
|
import type { Snippet } from 'svelte'
|
|
3
6
|
import { onMount } from 'svelte'
|
|
4
7
|
import IconPlayerPause from '@tabler/icons-svelte-runes/icons/player-pause'
|
|
@@ -31,11 +34,11 @@
|
|
|
31
34
|
|
|
32
35
|
<div class="grid gap-md w-full">
|
|
33
36
|
<div bind:this={element} data-playback={playing ? 'playing' : 'paused'}>{@render children?.()}</div>
|
|
34
|
-
<div class="ui-player" role="group" aria-label=
|
|
37
|
+
<div class="ui-player" role="group" aria-label={t('Animation controls')} data-state={playing ? 'playing' : 'paused'}>
|
|
35
38
|
<button type="button" class="ui-button" data-size="sm" onclick={() => control(playing ? 'pause' : 'play')}>
|
|
36
|
-
{#if playing}<IconPlayerPause aria-hidden="true" />{:else}<IconPlayerPlay aria-hidden="true" />{/if}{playing ? 'Pause' : 'Play'}
|
|
39
|
+
{#if playing}<IconPlayerPause aria-hidden="true" />{:else}<IconPlayerPlay aria-hidden="true" />{/if}{playing ? t('Pause') : t('Play')}
|
|
37
40
|
</button>
|
|
38
|
-
<button type="button" class="ui-button" data-size="sm" data-variant="quiet" onclick={() => control('restart')}><IconRefresh aria-hidden="true" />Replay</button>
|
|
41
|
+
<button type="button" class="ui-button" data-size="sm" data-variant="quiet" onclick={() => control('restart')}><IconRefresh aria-hidden="true" />{t('Replay')}</button>
|
|
39
42
|
<span class="ui-player-time"><output>{playing ? 'Playing' : 'Paused'}</output></span>
|
|
40
43
|
</div>
|
|
41
44
|
</div>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { getSite } from '@master/internal-site/site'
|
|
3
|
+
const { t } = getSite()
|
|
2
4
|
import '@master/internal-site/styles/system/specimens.css'
|
|
3
5
|
import DemoCopyButton from '@master/internal-site/demo/DemoCopyButton.svelte'
|
|
4
6
|
import DemoCopyGroup from '@master/internal-site/demo/DemoCopyGroup.svelte'
|
|
@@ -8,8 +10,8 @@
|
|
|
8
10
|
</script>
|
|
9
11
|
|
|
10
12
|
<div class="w-full"><DemoCopyGroup><div class="ui-palette">
|
|
11
|
-
{#each groups as { family, colors } (family)}<div class="ui-palette-row" role="group" aria-label={
|
|
13
|
+
{#each groups as { family, colors } (family)}<div class="ui-palette-row" role="group" aria-label={t('{family} palette').replace('{family}', family)}>
|
|
12
14
|
<span>{family}</span>
|
|
13
|
-
{#each colors as { name, value } (name)}<DemoCopyButton value={`var(--${name})`} label={
|
|
15
|
+
{#each colors as { name, value } (name)}<DemoCopyButton value={`var(--${name})`} label={t('Copy {name}').replace('{name}', name)} icon={null} class="ui-palette-chip" style={`background-color:${value}`} title={`${name}: ${value}`} />{/each}
|
|
14
16
|
</div>{/each}
|
|
15
17
|
</div></DemoCopyGroup></div>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { siteOf } from '@master/internal-site/astro/site-context'
|
|
3
|
+
const { t } = siteOf(Astro)
|
|
4
|
+
import '@master/internal-site/styles/system/compare.css'
|
|
2
5
|
import Demo from '@master/internal-site/demo/Demo.svelte'
|
|
3
6
|
import DemoViewport from '@master/internal-site/demo/DemoViewport.svelte'
|
|
4
7
|
|
|
@@ -17,9 +20,9 @@ const { html, css, height = 320, sizing = 'viewport', caption } = Astro.props
|
|
|
17
20
|
const document = (styles: string) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${styles.replaceAll('</style', '<\\/style')}</style></head><body>${html}</body></html>`
|
|
18
21
|
---
|
|
19
22
|
|
|
20
|
-
<Demo title="Browser defaults and author CSS" description="The same HTML in two documents" frame="none" caption={caption}>
|
|
23
|
+
<Demo title={t("Browser defaults and author CSS")} description={t("The same HTML in two documents")} frame="none" caption={caption}>
|
|
21
24
|
<div class="ui-compare">
|
|
22
|
-
<figure><figcaption>Browser defaults</figcaption><DemoViewport client:idle={{ timeout: 500 }} title="Browser defaults" document={document('')} height={height} sizing={sizing} /></figure>
|
|
23
|
-
<figure><figcaption>CSS applied</figcaption><DemoViewport client:idle={{ timeout: 500 }} title="CSS applied" document={document(css)} height={height} sizing={sizing} /></figure>
|
|
25
|
+
<figure><figcaption>{t("Browser defaults")}</figcaption><DemoViewport client:idle={{ timeout: 500 }} title={t("Browser defaults")} document={document('')} height={height} sizing={sizing} /></figure>
|
|
26
|
+
<figure><figcaption>{t("CSS applied")}</figcaption><DemoViewport client:idle={{ timeout: 500 }} title={t("CSS applied")} document={document(css)} height={height} sizing={sizing} /></figure>
|
|
24
27
|
</div>
|
|
25
28
|
</Demo>
|