@easyops-cn/a2ui-react 0.0.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.
Files changed (161) hide show
  1. package/.claude/commands/speckit.analyze.md +184 -0
  2. package/.claude/commands/speckit.checklist.md +294 -0
  3. package/.claude/commands/speckit.clarify.md +181 -0
  4. package/.claude/commands/speckit.constitution.md +82 -0
  5. package/.claude/commands/speckit.implement.md +135 -0
  6. package/.claude/commands/speckit.plan.md +89 -0
  7. package/.claude/commands/speckit.specify.md +256 -0
  8. package/.claude/commands/speckit.tasks.md +137 -0
  9. package/.claude/commands/speckit.taskstoissues.md +30 -0
  10. package/.github/workflows/deploy.yml +69 -0
  11. package/.husky/pre-commit +1 -0
  12. package/.prettierignore +4 -0
  13. package/.prettierrc +7 -0
  14. package/.specify/memory/constitution.md +73 -0
  15. package/.specify/scripts/bash/check-prerequisites.sh +166 -0
  16. package/.specify/scripts/bash/common.sh +156 -0
  17. package/.specify/scripts/bash/create-new-feature.sh +297 -0
  18. package/.specify/scripts/bash/setup-plan.sh +61 -0
  19. package/.specify/scripts/bash/update-agent-context.sh +799 -0
  20. package/.specify/templates/agent-file-template.md +28 -0
  21. package/.specify/templates/checklist-template.md +40 -0
  22. package/.specify/templates/plan-template.md +105 -0
  23. package/.specify/templates/spec-template.md +115 -0
  24. package/.specify/templates/tasks-template.md +250 -0
  25. package/CLAUDE.md +105 -0
  26. package/CONTRIBUTING.md +97 -0
  27. package/README.md +126 -0
  28. package/components.json +21 -0
  29. package/eslint.config.js +25 -0
  30. package/netlify.toml +50 -0
  31. package/package.json +94 -0
  32. package/playground/README.md +75 -0
  33. package/playground/index.html +22 -0
  34. package/playground/package.json +32 -0
  35. package/playground/public/favicon.svg +8 -0
  36. package/playground/src/App.css +256 -0
  37. package/playground/src/App.tsx +115 -0
  38. package/playground/src/assets/react.svg +1 -0
  39. package/playground/src/components/ErrorDisplay.tsx +13 -0
  40. package/playground/src/components/ExampleSelector.tsx +64 -0
  41. package/playground/src/components/Header.tsx +47 -0
  42. package/playground/src/components/JsonEditor.tsx +32 -0
  43. package/playground/src/components/Preview.tsx +78 -0
  44. package/playground/src/components/ThemeToggle.tsx +19 -0
  45. package/playground/src/data/examples.ts +1571 -0
  46. package/playground/src/hooks/useTheme.ts +55 -0
  47. package/playground/src/index.css +220 -0
  48. package/playground/src/main.tsx +10 -0
  49. package/playground/tsconfig.app.json +34 -0
  50. package/playground/tsconfig.json +13 -0
  51. package/playground/tsconfig.node.json +26 -0
  52. package/playground/vite.config.ts +31 -0
  53. package/specs/001-a2ui-renderer/checklists/requirements.md +41 -0
  54. package/specs/001-a2ui-renderer/data-model.md +140 -0
  55. package/specs/001-a2ui-renderer/plan.md +123 -0
  56. package/specs/001-a2ui-renderer/quickstart.md +141 -0
  57. package/specs/001-a2ui-renderer/research.md +140 -0
  58. package/specs/001-a2ui-renderer/spec.md +165 -0
  59. package/specs/001-a2ui-renderer/tasks.md +310 -0
  60. package/specs/002-playground/checklists/requirements.md +37 -0
  61. package/specs/002-playground/contracts/components.md +120 -0
  62. package/specs/002-playground/data-model.md +149 -0
  63. package/specs/002-playground/plan.md +73 -0
  64. package/specs/002-playground/quickstart.md +158 -0
  65. package/specs/002-playground/research.md +117 -0
  66. package/specs/002-playground/spec.md +109 -0
  67. package/specs/002-playground/tasks.md +224 -0
  68. package/src/0.8/A2UIRender.test.tsx +793 -0
  69. package/src/0.8/A2UIRender.tsx +142 -0
  70. package/src/0.8/components/ComponentRenderer.test.tsx +373 -0
  71. package/src/0.8/components/ComponentRenderer.tsx +163 -0
  72. package/src/0.8/components/UnknownComponent.tsx +49 -0
  73. package/src/0.8/components/display/AudioPlayerComponent.tsx +37 -0
  74. package/src/0.8/components/display/DividerComponent.tsx +23 -0
  75. package/src/0.8/components/display/IconComponent.tsx +137 -0
  76. package/src/0.8/components/display/ImageComponent.tsx +57 -0
  77. package/src/0.8/components/display/TextComponent.tsx +56 -0
  78. package/src/0.8/components/display/VideoComponent.tsx +31 -0
  79. package/src/0.8/components/display/display.test.tsx +660 -0
  80. package/src/0.8/components/display/index.ts +10 -0
  81. package/src/0.8/components/index.ts +14 -0
  82. package/src/0.8/components/interactive/ButtonComponent.tsx +44 -0
  83. package/src/0.8/components/interactive/CheckBoxComponent.tsx +45 -0
  84. package/src/0.8/components/interactive/DateTimeInputComponent.tsx +176 -0
  85. package/src/0.8/components/interactive/MultipleChoiceComponent.tsx +157 -0
  86. package/src/0.8/components/interactive/SliderComponent.tsx +53 -0
  87. package/src/0.8/components/interactive/TextFieldComponent.tsx +65 -0
  88. package/src/0.8/components/interactive/index.ts +10 -0
  89. package/src/0.8/components/interactive/interactive.test.tsx +618 -0
  90. package/src/0.8/components/layout/CardComponent.tsx +30 -0
  91. package/src/0.8/components/layout/ColumnComponent.tsx +93 -0
  92. package/src/0.8/components/layout/ListComponent.tsx +81 -0
  93. package/src/0.8/components/layout/ModalComponent.tsx +41 -0
  94. package/src/0.8/components/layout/RowComponent.tsx +94 -0
  95. package/src/0.8/components/layout/TabsComponent.tsx +59 -0
  96. package/src/0.8/components/layout/index.ts +10 -0
  97. package/src/0.8/components/layout/layout.test.tsx +558 -0
  98. package/src/0.8/contexts/A2UIProvider.test.tsx +226 -0
  99. package/src/0.8/contexts/A2UIProvider.tsx +54 -0
  100. package/src/0.8/contexts/ActionContext.test.tsx +242 -0
  101. package/src/0.8/contexts/ActionContext.tsx +105 -0
  102. package/src/0.8/contexts/ComponentsMapContext.tsx +125 -0
  103. package/src/0.8/contexts/DataModelContext.test.tsx +335 -0
  104. package/src/0.8/contexts/DataModelContext.tsx +184 -0
  105. package/src/0.8/contexts/SurfaceContext.test.tsx +339 -0
  106. package/src/0.8/contexts/SurfaceContext.tsx +197 -0
  107. package/src/0.8/hooks/useA2UIMessageHandler.test.tsx +399 -0
  108. package/src/0.8/hooks/useA2UIMessageHandler.ts +123 -0
  109. package/src/0.8/hooks/useComponent.test.tsx +148 -0
  110. package/src/0.8/hooks/useComponent.ts +39 -0
  111. package/src/0.8/hooks/useDataBinding.test.tsx +334 -0
  112. package/src/0.8/hooks/useDataBinding.ts +99 -0
  113. package/src/0.8/hooks/useDispatchAction.test.tsx +83 -0
  114. package/src/0.8/hooks/useDispatchAction.ts +35 -0
  115. package/src/0.8/hooks/useSurface.test.tsx +114 -0
  116. package/src/0.8/hooks/useSurface.ts +34 -0
  117. package/src/0.8/index.ts +38 -0
  118. package/src/0.8/schemas/client_to_server.json +50 -0
  119. package/src/0.8/schemas/server_to_client.json +148 -0
  120. package/src/0.8/schemas/standard_catalog_definition.json +661 -0
  121. package/src/0.8/types/index.ts +448 -0
  122. package/src/0.8/utils/dataBinding.test.ts +443 -0
  123. package/src/0.8/utils/dataBinding.ts +212 -0
  124. package/src/0.8/utils/pathUtils.test.ts +353 -0
  125. package/src/0.8/utils/pathUtils.ts +200 -0
  126. package/src/components/ui/button.tsx +62 -0
  127. package/src/components/ui/calendar.tsx +220 -0
  128. package/src/components/ui/card.tsx +92 -0
  129. package/src/components/ui/checkbox.tsx +30 -0
  130. package/src/components/ui/dialog.tsx +141 -0
  131. package/src/components/ui/input.tsx +21 -0
  132. package/src/components/ui/label.tsx +22 -0
  133. package/src/components/ui/native-select.tsx +53 -0
  134. package/src/components/ui/popover.tsx +46 -0
  135. package/src/components/ui/select.tsx +188 -0
  136. package/src/components/ui/separator.tsx +26 -0
  137. package/src/components/ui/slider.tsx +61 -0
  138. package/src/components/ui/tabs.tsx +64 -0
  139. package/src/components/ui/textarea.tsx +18 -0
  140. package/src/index.ts +1 -0
  141. package/src/lib/utils.ts +6 -0
  142. package/tsconfig.json +28 -0
  143. package/vite.config.ts +29 -0
  144. package/vitest.config.ts +22 -0
  145. package/vitest.setup.ts +8 -0
  146. package/website/README.md +4 -0
  147. package/website/assets/favicon.svg +8 -0
  148. package/website/content/.gitkeep +0 -0
  149. package/website/content/index.md +122 -0
  150. package/website/global.d.ts +9 -0
  151. package/website/package.json +17 -0
  152. package/website/plain.config.js +28 -0
  153. package/website/serve.json +6 -0
  154. package/website/src/client/color-mode-switch.css +47 -0
  155. package/website/src/client/index.js +61 -0
  156. package/website/src/client/moon.svg +1 -0
  157. package/website/src/client/sun.svg +1 -0
  158. package/website/src/components/Footer.jsx +9 -0
  159. package/website/src/components/Header.jsx +44 -0
  160. package/website/src/components/Page.jsx +28 -0
  161. package/website/src/global.css +423 -0
@@ -0,0 +1,47 @@
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ :host([hidden]) {
6
+ display: none;
7
+ }
8
+
9
+ a {
10
+ cursor: pointer;
11
+ display: block;
12
+ padding: 6px;
13
+ border-radius: 8px;
14
+ }
15
+
16
+ a:hover {
17
+ background-color: var(--muted-color);
18
+ }
19
+
20
+ a:focus {
21
+ outline: 2px solid var(--text-color);
22
+ outline-offset: 2px;
23
+ }
24
+
25
+ svg {
26
+ display: block;
27
+ }
28
+
29
+ .lucide {
30
+ width: 1em;
31
+ height: 1em;
32
+ font-size: 1.5rem;
33
+ }
34
+
35
+ .lucide-moon {
36
+ display: none;
37
+ }
38
+
39
+ a[data-theme='dark'] {
40
+ .lucide-moon {
41
+ display: block;
42
+ }
43
+
44
+ .lucide-sun {
45
+ display: none;
46
+ }
47
+ }
@@ -0,0 +1,61 @@
1
+ // @ts-check
2
+ import ColorModeCss from './color-mode-switch.css'
3
+ import MoonSvg from './moon.svg'
4
+ import SunSvg from './sun.svg'
5
+
6
+ if (CSS.supports('color-scheme', 'dark')) {
7
+ customElements.define(
8
+ 'color-mode-switch',
9
+ class ColorModeSwitchElement extends HTMLElement {
10
+ /** @type {HTMLElement} */
11
+ _switch
12
+
13
+ constructor() {
14
+ super()
15
+
16
+ const shadowRoot = this.attachShadow({
17
+ mode: 'open',
18
+ delegatesFocus: true,
19
+ })
20
+
21
+ shadowRoot.innerHTML = `<style>${ColorModeCss}</style><a role="button" tabindex="0">${MoonSvg}${SunSvg}</a>`
22
+
23
+ // @ts-ignore
24
+ this._switch = shadowRoot.querySelector('a')
25
+ this._setTheme(localStorage.getItem('theme') || getPreferColorScheme())
26
+ }
27
+
28
+ _clickHandler = () => {
29
+ const currentTheme = document.documentElement.dataset.theme
30
+ const nextTheme = currentTheme === 'dark' ? 'light' : 'dark'
31
+ this._setTheme(nextTheme, true)
32
+ }
33
+
34
+ /**
35
+ * @param {string} theme
36
+ * @param {boolean=} force
37
+ */
38
+ _setTheme(theme, force) {
39
+ document.documentElement.dataset.theme = theme
40
+ this._switch.dataset.theme = theme
41
+ if (force) {
42
+ localStorage.setItem('theme', theme)
43
+ }
44
+ }
45
+
46
+ connectedCallback() {
47
+ this._switch.addEventListener('click', this._clickHandler)
48
+ }
49
+
50
+ disconnectedCallback() {
51
+ this._switch.removeEventListener('click', this._clickHandler)
52
+ }
53
+ }
54
+ )
55
+
56
+ function getPreferColorScheme() {
57
+ return window.matchMedia?.('(prefers-color-scheme: dark)').matches
58
+ ? 'dark'
59
+ : 'light'
60
+ }
61
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon-icon lucide-moon"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
@@ -0,0 +1,9 @@
1
+ export default function Footer() {
2
+ return (
3
+ <footer>
4
+ © {new Date().getFullYear()} • Built with{' '}
5
+ <a href="https://github.com/weareoutman/plain-blog">Plain Blog</a> •{' '}
6
+ <a href="https://github.com/easyops-cn/a2ui-react">GitHub</a>
7
+ </footer>
8
+ )
9
+ }
@@ -0,0 +1,44 @@
1
+ import { useSiteContext } from 'plain-blog/SiteContext'
2
+
3
+ export default function Header() {
4
+ const { baseUrl, site } = useSiteContext()
5
+
6
+ return (
7
+ <header>
8
+ <h1>
9
+ <a href={baseUrl}>{site.title}</a>
10
+ </h1>
11
+ <div className="header-right">
12
+ <nav className="header-nav">
13
+ <a href={baseUrl} className="active">
14
+ Docs
15
+ </a>
16
+ <a href={`${baseUrl}playground/`}>Playground</a>
17
+ <a
18
+ href="https://github.com/easyops-cn/a2ui-react"
19
+ target="_blank"
20
+ rel="noopener noreferrer"
21
+ >
22
+ GitHub
23
+ <svg
24
+ xmlns="http://www.w3.org/2000/svg"
25
+ width="14"
26
+ height="14"
27
+ viewBox="0 0 24 24"
28
+ fill="none"
29
+ stroke="currentColor"
30
+ strokeWidth="2"
31
+ strokeLinecap="round"
32
+ strokeLinejoin="round"
33
+ >
34
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
35
+ <polyline points="15 3 21 3 21 9" />
36
+ <line x1="10" y1="14" x2="21" y2="3" />
37
+ </svg>
38
+ </a>
39
+ </nav>
40
+ <color-mode-switch />
41
+ </div>
42
+ </header>
43
+ )
44
+ }
@@ -0,0 +1,28 @@
1
+ import { useSiteContext } from 'plain-blog/SiteContext'
2
+
3
+ export default function Page({ title, meta, children }) {
4
+ const { stylesheets, site, locales, scripts } = useSiteContext()
5
+
6
+ return (
7
+ <html lang={title === 'Introducing Plain Blog' ? 'en-US' : locales?.[0]}>
8
+ <head>
9
+ <meta charSet="utf-8" />
10
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
11
+ <title>{title}</title>
12
+ {meta &&
13
+ Object.entries(meta).map(
14
+ ([name, content]) =>
15
+ content && <meta key="name" name={name} content={content} />
16
+ )}
17
+ {site.favicon && <link rel="icon" href={site.favicon} />}
18
+ {stylesheets?.map((url) => (
19
+ <link key={url} rel="stylesheet" href={url} />
20
+ ))}
21
+ {scripts?.map((url) => (
22
+ <script key={url} src={url} async />
23
+ ))}
24
+ </head>
25
+ <body>{children}</body>
26
+ </html>
27
+ )
28
+ }
@@ -0,0 +1,423 @@
1
+ html {
2
+ --primary-color: #009488;
3
+ --text-color: hsl(10, 20%, 20%);
4
+ --muted-color: hsl(10, 20%, 94%);
5
+ --background-color: hsl(10, 10%, 98%);
6
+
7
+ color-scheme: light;
8
+ background-color: var(--background-color);
9
+ color: var(--text-color);
10
+ }
11
+
12
+ @media (prefers-color-scheme: dark) {
13
+ html:not([data-theme='light']) {
14
+ --primary-color: #80cbc4;
15
+ --text-color: hsl(210, 50%, 96%);
16
+ --muted-color: rgb(64, 71, 86);
17
+ --background-color: hsl(230, 25%, 18%);
18
+
19
+ color-scheme: dark;
20
+ -webkit-font-smoothing: antialiased;
21
+ -moz-osx-font-smoothing: grayscale;
22
+ }
23
+ }
24
+
25
+ html[data-theme='dark'] {
26
+ --primary-color: #80cbc4;
27
+ --text-color: hsl(210, 50%, 96%);
28
+ --muted-color: rgb(64, 71, 86);
29
+ --background-color: hsl(230, 25%, 18%);
30
+
31
+ color-scheme: dark;
32
+ -webkit-font-smoothing: antialiased;
33
+ -moz-osx-font-smoothing: grayscale;
34
+ }
35
+
36
+ * {
37
+ box-sizing: border-box;
38
+ }
39
+
40
+ body {
41
+ font-family:
42
+ system-ui,
43
+ -apple-system,
44
+ Segoe UI,
45
+ Roboto,
46
+ Ubuntu,
47
+ Cantarell,
48
+ Noto Sans,
49
+ sans-serif,
50
+ 'Segoe UI',
51
+ 'Roboto',
52
+ 'Ubuntu',
53
+ 'Cantarell',
54
+ 'Noto Sans',
55
+ sans-serif,
56
+ 'Apple Color Emoji',
57
+ 'Segoe UI Emoji',
58
+ 'Segoe UI Symbol',
59
+ 'Noto Color Emoji';
60
+ line-height: 1.75;
61
+ font-weight: 400;
62
+ font-size: 16px;
63
+ margin: 0;
64
+ }
65
+
66
+ h1 {
67
+ font-size: 32px;
68
+ font-weight: 700;
69
+ line-height: 1.25;
70
+ }
71
+
72
+ h2 {
73
+ font-size: 24px;
74
+ }
75
+
76
+ h3 {
77
+ font-size: 20px;
78
+ }
79
+
80
+ a {
81
+ color: var(--primary-color);
82
+ text-decoration: none;
83
+ box-shadow: 0 1px 0 0 currentColor;
84
+ }
85
+
86
+ h1 > a,
87
+ h2 > a,
88
+ h3 > a {
89
+ color: inherit;
90
+
91
+ &:not(:hover) {
92
+ box-shadow: none;
93
+ }
94
+ }
95
+
96
+ body > header,
97
+ body > footer,
98
+ body > main {
99
+ width: 100%;
100
+ max-width: 1240px;
101
+ margin-left: auto;
102
+ margin-right: auto;
103
+ }
104
+
105
+ body > header,
106
+ body > footer,
107
+ body > main > section,
108
+ body > main > article,
109
+ body > main > nav {
110
+ padding: 16px;
111
+ }
112
+
113
+ body > header {
114
+ display: flex;
115
+ flex-wrap: wrap;
116
+ align-items: center;
117
+ justify-content: space-between;
118
+ gap: 8px;
119
+ padding-top: 24px;
120
+ }
121
+
122
+ .header-right {
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: space-between;
126
+ gap: 16px;
127
+ }
128
+
129
+ .header-nav {
130
+ display: flex;
131
+ align-items: center;
132
+ gap: 8px;
133
+ }
134
+
135
+ .header-nav a {
136
+ color: var(--text-color);
137
+ font-size: 16px;
138
+ font-weight: 500;
139
+ box-shadow: none;
140
+ padding: 6px 8px;
141
+ transition: color 0.2s ease;
142
+ }
143
+
144
+ .header-nav a:hover {
145
+ color: var(--primary-color);
146
+ text-decoration: underline;
147
+ text-underline-offset: 4px;
148
+ }
149
+
150
+ .header-nav a.active {
151
+ color: var(--primary-color);
152
+ text-decoration: underline;
153
+ text-underline-offset: 4px;
154
+ }
155
+
156
+ .header-nav a[target='_blank'] {
157
+ display: inline-flex;
158
+ align-items: center;
159
+ gap: 0.25em;
160
+ }
161
+
162
+ body > header > a {
163
+ box-shadow: none;
164
+ text-decoration: none;
165
+ color: var(--primary-color);
166
+ font-size: 24px;
167
+ font-weight: 700;
168
+ }
169
+
170
+ body > header {
171
+ padding-top: 32px;
172
+ }
173
+
174
+ body > header h1 {
175
+ margin: 0;
176
+ font-size: 20px;
177
+ color: var(--primary-color);
178
+ }
179
+
180
+ body > header h1 > a {
181
+ box-shadow: none;
182
+ text-decoration: none;
183
+ }
184
+
185
+ body > header h1 > a:not(:hover) {
186
+ color: inherit;
187
+ }
188
+
189
+ body > footer {
190
+ padding-bottom: 32px;
191
+ }
192
+
193
+ body > footer > hr {
194
+ border-width: 0 0 1px;
195
+ border-style: solid;
196
+ border-color: var(--muted-color);
197
+ }
198
+
199
+ body > main:has(> article) {
200
+ display: flex;
201
+ }
202
+
203
+ body > main > article {
204
+ max-width: 80%;
205
+ min-width: 0;
206
+ flex: 1 0;
207
+ }
208
+
209
+ body > main > nav {
210
+ max-width: 20%;
211
+ min-width: 0;
212
+ flex: 0 0 20%;
213
+ font-size: 13px;
214
+ position: sticky;
215
+ top: 0;
216
+ max-height: calc(100vh - 100px);
217
+ overflow-y: auto;
218
+
219
+ ul {
220
+ list-style: none;
221
+ margin: 0;
222
+ padding-left: 8px;
223
+ }
224
+
225
+ li {
226
+ margin: 8px;
227
+ }
228
+
229
+ & > ul {
230
+ border-left: 1px solid var(--muted-color);
231
+ }
232
+ }
233
+
234
+ article > p,
235
+ article > blockquote > p {
236
+ margin-top: 16px;
237
+ margin-bottom: 16px;
238
+ }
239
+
240
+ article > p > a > img,
241
+ article > p > img {
242
+ display: block;
243
+ max-width: 100%;
244
+ margin-left: auto;
245
+ margin-right: auto;
246
+ }
247
+
248
+ :not(pre) > code {
249
+ font-family:
250
+ Menlo, Monaco, Consolas, 'Andale Mono', 'Ubuntu Mono', 'Courier New',
251
+ monospace;
252
+ background-color: var(--muted-color);
253
+ padding: 0.125em 0.25em 0.125em;
254
+ border-radius: 0.25em;
255
+ }
256
+
257
+ a > code {
258
+ padding-bottom: 0.05em;
259
+ }
260
+
261
+ article blockquote {
262
+ padding-left: 32px;
263
+ padding-right: 32px;
264
+ margin-left: 0px;
265
+ margin-right: 0px;
266
+ border-left: 5px solid rgb(204, 204, 204);
267
+ opacity: 0.8;
268
+ }
269
+
270
+ article table {
271
+ width: 100%;
272
+ margin-top: 16px;
273
+ margin-bottom: 16px;
274
+ border-collapse: separate;
275
+ border-spacing: 0px;
276
+ }
277
+
278
+ article th,
279
+ article td {
280
+ text-align: left;
281
+ padding: 4px 4px 4px 0px;
282
+ border-color: var(--muted-color);
283
+ border-bottom-style: solid;
284
+ }
285
+
286
+ article p.post-date {
287
+ font-size: 14px;
288
+ margin-top: -16px;
289
+ margin-bottom: 16px;
290
+ }
291
+
292
+ .shiki {
293
+ margin-left: -16px;
294
+ margin-right: -16px;
295
+ padding: 16px;
296
+ font-size: 14px;
297
+ line-height: 1.75;
298
+ overflow-x: auto;
299
+ outline: 1px solid var(--muted-color);
300
+ }
301
+
302
+ p.figure-caption {
303
+ text-align: center;
304
+ opacity: 0.6;
305
+ font-size: 87.5%;
306
+ margin-top: -14px;
307
+ font-style: italic;
308
+
309
+ width: fit-content;
310
+ max-width: 90%;
311
+ margin-left: auto;
312
+ margin-right: auto;
313
+ border-bottom: 1px solid #ccc;
314
+ padding-left: 28px;
315
+ padding-right: 28px;
316
+ padding-bottom: 7px;
317
+ }
318
+
319
+ hr.divider {
320
+ border: none;
321
+ font-size: 150%;
322
+ letter-spacing: 0.6em;
323
+ margin-bottom: 42px;
324
+ text-align: center;
325
+ }
326
+
327
+ hr.divider::before {
328
+ content: '...';
329
+ }
330
+
331
+ footer > hr {
332
+ margin-bottom: 16px;
333
+ }
334
+
335
+ a[role='button'] {
336
+ cursor: pointer;
337
+ }
338
+
339
+ .search-mark {
340
+ box-shadow: 0 1px 0 0 currentColor;
341
+ }
342
+
343
+ /* color-mode-switch:not(:defined) {
344
+ display: none;
345
+ } */
346
+
347
+ @media screen and (max-width: 996px) {
348
+ body > main > nav {
349
+ display: none;
350
+ }
351
+
352
+ body > main > article {
353
+ max-width: 992px;
354
+ }
355
+ }
356
+
357
+ @media screen and (max-width: 703px) {
358
+ body > header h1 {
359
+ flex: 0 0 100%;
360
+ }
361
+
362
+ .header-right {
363
+ flex: 0 0 calc(100% + 6px);
364
+ margin-left: -6px;
365
+ }
366
+ }
367
+
368
+ @media screen and (max-width: 1271px) and (min-width: 704px) {
369
+ .shiki {
370
+ margin-left: 0;
371
+ margin-right: 0;
372
+ }
373
+ }
374
+
375
+ @media screen and (min-width: 704px) {
376
+ h1 {
377
+ font-size: 40px;
378
+ }
379
+ h2 {
380
+ font-size: 32px;
381
+ }
382
+ h3 {
383
+ font-size: 24px;
384
+ }
385
+ h4 {
386
+ font-size: 20px;
387
+ }
388
+
389
+ body > header h1 {
390
+ font-size: 24px;
391
+ line-height: 36px;
392
+ }
393
+
394
+ .shiki {
395
+ border-radius: 10px;
396
+ }
397
+ }
398
+
399
+ @media (prefers-color-scheme: dark) {
400
+ html:not([data-theme='light']) {
401
+ .shiki,
402
+ .shiki span {
403
+ color: var(--shiki-dark) !important;
404
+ background-color: var(--shiki-dark-bg) !important;
405
+ /* Optional, if you also want font styles */
406
+ font-style: var(--shiki-dark-font-style) !important;
407
+ font-weight: var(--shiki-dark-font-weight) !important;
408
+ text-decoration: var(--shiki-dark-text-decoration) !important;
409
+ }
410
+ }
411
+ }
412
+
413
+ html[data-theme='dark'] {
414
+ .shiki,
415
+ .shiki span {
416
+ color: var(--shiki-dark) !important;
417
+ background-color: var(--shiki-dark-bg) !important;
418
+ /* Optional, if you also want font styles */
419
+ font-style: var(--shiki-dark-font-style) !important;
420
+ font-weight: var(--shiki-dark-font-weight) !important;
421
+ text-decoration: var(--shiki-dark-text-decoration) !important;
422
+ }
423
+ }