@mhmo91/schmancy 0.10.2 → 0.10.4
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/.claude-plugin/plugin.json +1 -1
- package/README.md +21 -19
- package/custom-elements.json +0 -13
- package/dist/.claude-plugin/plugin.json +1 -1
- package/dist/agent/schmancy.agent.js +5328 -8538
- package/dist/agent/schmancy.agent.js.map +1 -1
- package/dist/agent/schmancy.manifest.json +1 -13
- package/dist/handover/agent-runtime-followups.md +1 -1
- package/dist/handover/agent-runtime-v1.md +3 -3
- package/package.json +1 -1
- package/plugins/vite-plugin-schmancy-manifest.ts +0 -13
- package/src/agent/agent-entry.test.ts +15 -0
- package/src/agent/agent-entry.ts +11 -16
- package/types/src/agent/agent-entry.d.ts +2 -3
- package/src/agent/agent-bundle.test.ts +0 -92
- package/src/agent/helpers.ts +0 -159
- package/src/agent/schmancy-skill.ts +0 -71
- package/src/agent/virtual-manifest.d.ts +0 -10
- package/types/src/agent/helpers.d.ts +0 -86
- package/types/src/agent/schmancy-skill.d.ts +0 -32
- /package/types/src/agent/{agent-bundle.test.d.ts → agent-entry.test.d.ts} +0 -0
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"readme": "# Schmancy\n\nA Web Component UI library built on Lit, RxJS, and Tailwind CSS. Surfaces are glass. Depth is light. Interactions are physics.\n\n## Agent runtime\n\nFor sandboxed-iframe agents (Claude Design, Claude Artifacts, any LLM that can\nonly write HTML), schmancy ships a single-URL runtime at `@mhmo91/schmancy/agent`.\nDrop one `<script type=\"module\">` tag and every `<schmancy-*>` element is\nregistered. No bundler, no bare specifiers, no npm install.\n\n```html\n<script type=\"module\">\n import
|
|
3
|
+
"readme": "# Schmancy\n\nA Web Component UI library built on Lit, RxJS, and Tailwind CSS. Surfaces are glass. Depth is light. Interactions are physics.\n\n## Agent runtime\n\nFor sandboxed-iframe agents (Claude Design, Claude Artifacts, any LLM that can\nonly write HTML), schmancy ships a single-URL runtime at `@mhmo91/schmancy/agent`.\nDrop one `<script type=\"module\">` tag and every `<schmancy-*>` element is\nregistered. No bundler, no bare specifiers, no npm install.\n\n```html\n<script type=\"module\">\n import 'https://esm.sh/@mhmo91/schmancy/agent';\n</script>\n<schmancy-theme root scheme=\"dark\">\n <schmancy-surface type=\"solid\" fill=\"all\">\n <schmancy-button>Hi</schmancy-button>\n </schmancy-surface>\n</schmancy-theme>\n```\n\nThe same entry re-exports the full library surface for in-page script\ncode (`theme`, `area`, `state`, `show`, `lazy`, every directive, every\nservice, `SchmancyElement`). Import from the same URL.\n\nFor introspection — every tag's attributes, events, slots, CSS parts,\nplus the enum `values` array on every typed attribute (so agents don't\nhave to parse `\"'filled' | 'tonal' | ...\"` strings) — read the static\nmanifest at `@mhmo91/schmancy/agent/manifest`. It's a JSON file, shape\nfollows Custom Elements Manifest v1.\n\n## Install\n\n```bash\nnpm install @mhmo91/schmancy\n```\n\n```typescript\nimport '@mhmo91/schmancy'\nimport { magnetic, cursorGlow, gravity } from '@mhmo91/schmancy/directives'\n```\n\n## Use with Claude Code\n\nSchmancy ships a Claude Code plugin (manifest at `.claude-plugin/plugin.json`,\nskill source under `skills/schmancy/`). The npm tarball includes both, so\nafter `npm install @mhmo91/schmancy`, point Claude at the package directory\nwhen launching:\n\n```\nclaude --plugin-dir node_modules/@mhmo91/schmancy\n```\n\nSet a shell alias / `.envrc` so every session in the project picks it up.\nAfter editing plugin files, run `/reload-plugins` inside the session.\n\nClaude now knows every Schmancy component, foundation pattern, and\nconvention; the skill activates automatically when you work on schmancy\ncode — no CLAUDE.md edits, no symlinks.\n\n## Quick Start\n\n```html\n<schmancy-theme root scheme=\"dark\">\n <schmancy-surface type=\"solid\" fill=\"all\">\n <schmancy-area name=\"root\" .default=${lazy(() => import('./home.page'))}>\n <schmancy-route when=\"home-page\" .component=${lazy(() => import('./home.page'))} />\n </schmancy-area>\n </schmancy-surface>\n</schmancy-theme>\n```\n\n## Design: Luminous Glass\n\n| Surface | Opacity | Blur | Purpose |\n|---------|---------|------|---------|\n| `solid` | 92% | — | Dense glass, high readability |\n| `subtle` | 78% | 8px | Frosted panel (default) |\n| `glass` | 55% | 16px | Overlays, dialogs, dropdowns |\n| `luminous` | 42% | 20px | Hero panels with glow halo |\n\n## Docs\n\nSchmancy is organized in four layers:\n\n- **Foundations** — [Area](./skills/schmancy/area.md) · [State](./skills/schmancy/state.md) · [Mixins (SchmancyElement)](./skills/schmancy/mixins.md) · [Theme](./skills/schmancy/theme.md) · [Directives](./skills/schmancy/directives.md)\n- **Atoms** — [Typography](./skills/schmancy/typography.md) · [Icons](./skills/schmancy/icons.md) · [Button](./skills/schmancy/button.md) · [Surface](./skills/schmancy/surface.md) · [Divider](./skills/schmancy/divider.md) · [Avatar](./skills/schmancy/avatar.md)\n- **Composites (by job)** — Forms, Navigation, Overlays, Interaction, Feedback, Display\n- **Utilities** — [Animation](./skills/schmancy/animation.md) · [Audio](./skills/schmancy/audio.md) · [Discovery](./skills/schmancy/discovery.md) · [RxJS Utils](./skills/schmancy/rxjs-utils.md) · [Utils](./skills/schmancy/utils.md)\n\n**Full component index:** [skills/schmancy/INDEX.md](./skills/schmancy/INDEX.md) — the single-file map with every tag, service, and convention. Written primarily for AI agents; humans welcome.\n\n## Tech Stack\n\n[Lit](https://lit.dev) · [RxJS](https://rxjs.dev) · [Tailwind CSS v4](https://tailwindcss.com) · [Blackbird](./src/utils/animation.ts)\n\n## License\n\nApache-2.0\n",
|
|
4
4
|
"modules": [
|
|
5
|
-
{
|
|
6
|
-
"kind": "javascript-module",
|
|
7
|
-
"path": "agent/schmancy-skill.ts",
|
|
8
|
-
"declarations": [
|
|
9
|
-
{
|
|
10
|
-
"kind": "class",
|
|
11
|
-
"name": "SchmancySkill",
|
|
12
|
-
"tagName": "schmancy-skill",
|
|
13
|
-
"description": "Self-describing runtime helper. Drop `<schmancy-skill></schmancy-skill>` once on a page and `window.schmancy.help('schmancy-button')` returns the machine-readable entry for any tag. Renders nothing."
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
5
|
{
|
|
18
6
|
"kind": "javascript-module",
|
|
19
7
|
"path": "area/area.component.ts",
|
|
@@ -203,7 +203,7 @@ The manifest already has everything needed; the package is just the JSON-RPC wra
|
|
|
203
203
|
|
|
204
204
|
**Problem.** `handover/agent-runtime-v1.md` had `<PENDING>` placeholders that we manually replaced with `0.9.13` after the first publish. Future handover docs will have the same issue.
|
|
205
205
|
|
|
206
|
-
**Fix.** A build step that substitutes `0.10.
|
|
206
|
+
**Fix.** A build step that substitutes `0.10.4` in `handover/**/*.md` against `package.json`'s `version` field on every build. `dist/handover/**/*.md` gets the rendered version; the source stays templated.
|
|
207
207
|
|
|
208
208
|
**Effort:** ~30 min (one sed step or a tiny script).
|
|
209
209
|
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
## The URLs you asked for
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
https://esm.sh/@mhmo91/schmancy/agent@0.10.
|
|
11
|
-
https://esm.sh/@mhmo91/schmancy/agent/manifest@0.10.
|
|
10
|
+
https://esm.sh/@mhmo91/schmancy/agent@0.10.4
|
|
11
|
+
https://esm.sh/@mhmo91/schmancy/agent/manifest@0.10.4
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
`0.9.13` is the first release containing `/agent`; every subsequent publish serves the same subpath. `npm view @mhmo91/schmancy version` always returns the current pin if you want to float forward.
|
|
@@ -20,7 +20,7 @@ One script tag. No bundler, no bare specifiers, no npm install.
|
|
|
20
20
|
```html
|
|
21
21
|
<!doctype html>
|
|
22
22
|
<script type="module">
|
|
23
|
-
import { $dialog, theme } from 'https://esm.sh/@mhmo91/schmancy/agent@0.10.
|
|
23
|
+
import { $dialog, theme } from 'https://esm.sh/@mhmo91/schmancy/agent@0.10.4';
|
|
24
24
|
</script>
|
|
25
25
|
<schmancy-theme root scheme="dark">
|
|
26
26
|
<schmancy-surface type="solid" fill="all">
|
package/package.json
CHANGED
|
@@ -3,8 +3,6 @@ import { resolve } from 'node:path'
|
|
|
3
3
|
import { Project, type ClassDeclaration, type SourceFile } from 'ts-morph'
|
|
4
4
|
import type { Plugin } from 'vite'
|
|
5
5
|
|
|
6
|
-
const VIRTUAL_ID = 'virtual:schmancy-manifest'
|
|
7
|
-
const RESOLVED_VIRTUAL_ID = '\0' + VIRTUAL_ID
|
|
8
6
|
|
|
9
7
|
type Attribute = {
|
|
10
8
|
name: string
|
|
@@ -415,17 +413,6 @@ export default function schmancyManifestPlugin(options: SchmancyManifestPluginOp
|
|
|
415
413
|
compute()
|
|
416
414
|
},
|
|
417
415
|
|
|
418
|
-
resolveId(id) {
|
|
419
|
-
if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID
|
|
420
|
-
return null
|
|
421
|
-
},
|
|
422
|
-
|
|
423
|
-
load(id) {
|
|
424
|
-
if (id !== RESOLVED_VIRTUAL_ID) return null
|
|
425
|
-
const manifest = cachedManifest ?? compute()
|
|
426
|
-
return `export default ${JSON.stringify(manifest)};`
|
|
427
|
-
},
|
|
428
|
-
|
|
429
416
|
generateBundle() {
|
|
430
417
|
const manifest = cachedManifest ?? compute()
|
|
431
418
|
this.emitFile({
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import './agent-entry'
|
|
3
|
+
|
|
4
|
+
// Minimal smoke gate for the publish workflow. Loads the agent bundle entry
|
|
5
|
+
// in a real browser and asserts that the side-effect tag registration the
|
|
6
|
+
// esm.sh script-tag use case relies on actually fires. If the entry throws
|
|
7
|
+
// at import time or fails to register a representative tag, the publish step
|
|
8
|
+
// fails before the package goes out.
|
|
9
|
+
describe('agent bundle', () => {
|
|
10
|
+
it('registers core schmancy-* tags on import', () => {
|
|
11
|
+
expect(customElements.get('schmancy-button')).toBeDefined()
|
|
12
|
+
expect(customElements.get('schmancy-theme')).toBeDefined()
|
|
13
|
+
expect(customElements.get('schmancy-surface')).toBeDefined()
|
|
14
|
+
})
|
|
15
|
+
})
|
package/src/agent/agent-entry.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
+
// Single-URL bundle for sandboxed-iframe agents (Claude Design, Artifacts,
|
|
2
|
+
// any host that can only write HTML and consume one esm.sh URL). Side-effect
|
|
3
|
+
// import of the root registers every `<schmancy-*>` tag; re-exporting the
|
|
4
|
+
// root gives in-page script code the full library surface from the same URL.
|
|
5
|
+
//
|
|
6
|
+
// `SchmancyElement` is re-exported from `../../mixins/index` because the
|
|
7
|
+
// root index doesn't currently surface mixins. The deprecated `$LitElement`
|
|
8
|
+
// alias is intentionally NOT re-exported here — agent contexts get the
|
|
9
|
+
// canonical base class.
|
|
1
10
|
import '../index'
|
|
2
|
-
import './schmancy-skill'
|
|
3
11
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
$notify,
|
|
7
|
-
sheet,
|
|
8
|
-
SchmancySheetPosition,
|
|
9
|
-
schmancyContentDrawer,
|
|
10
|
-
theme,
|
|
11
|
-
area,
|
|
12
|
-
lazy,
|
|
13
|
-
state,
|
|
14
|
-
bindState,
|
|
15
|
-
computed,
|
|
16
|
-
stateFromObservable,
|
|
17
|
-
} from '../index'
|
|
18
|
-
export { $LitElement } from '../../mixins/index'
|
|
12
|
+
export * from '../index'
|
|
13
|
+
export { SchmancyElement } from '../../mixins/index'
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import '../index';
|
|
2
|
-
|
|
3
|
-
export {
|
|
4
|
-
export { $LitElement } from '../../mixins/index';
|
|
2
|
+
export * from '../index';
|
|
3
|
+
export { SchmancyElement } from '../../mixins/index';
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import './agent-entry'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Acceptance test per the Claude Design handover §4.4:
|
|
6
|
-
*
|
|
7
|
-
* > "CI check: load the bundle in a headless browser, assert
|
|
8
|
-
* > `customElements.get('schmancy-button')` resolves, assert
|
|
9
|
-
* > `window.schmancy.help()` returns non-empty."
|
|
10
|
-
*
|
|
11
|
-
* This test is the runtime smoke test. It imports the agent bundle entry
|
|
12
|
-
* (which side-effect registers every <schmancy-*> tag plus <schmancy-skill>)
|
|
13
|
-
* and then verifies the self-describing surface is installed.
|
|
14
|
-
*/
|
|
15
|
-
describe('agent bundle — handover §4.4 acceptance', () => {
|
|
16
|
-
it('registers `schmancy-button` on import', () => {
|
|
17
|
-
expect(customElements.get('schmancy-button')).toBeDefined()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('registers `schmancy-skill` on import', () => {
|
|
21
|
-
expect(customElements.get('schmancy-skill')).toBeDefined()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('installs `window.schmancy` when a <schmancy-skill> connects', async () => {
|
|
25
|
-
const host = document.createElement('div')
|
|
26
|
-
const skill = document.createElement('schmancy-skill')
|
|
27
|
-
host.appendChild(skill)
|
|
28
|
-
document.body.appendChild(host)
|
|
29
|
-
|
|
30
|
-
await customElements.whenDefined('schmancy-skill')
|
|
31
|
-
// One microtask for connectedCallback to finish installing globals.
|
|
32
|
-
await new Promise(requestAnimationFrame)
|
|
33
|
-
|
|
34
|
-
expect(typeof window.schmancy).toBe('object')
|
|
35
|
-
expect(typeof window.schmancy?.help).toBe('function')
|
|
36
|
-
expect(typeof window.schmancy?.tokens).toBe('function')
|
|
37
|
-
expect(typeof window.schmancy?.capabilities).toBe('function')
|
|
38
|
-
|
|
39
|
-
host.remove()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('`window.schmancy.help()` returns a non-empty manifest summary', async () => {
|
|
43
|
-
const skill = document.createElement('schmancy-skill')
|
|
44
|
-
document.body.appendChild(skill)
|
|
45
|
-
await customElements.whenDefined('schmancy-skill')
|
|
46
|
-
await new Promise(requestAnimationFrame)
|
|
47
|
-
|
|
48
|
-
const help = window.schmancy!.help() as { elements: unknown[]; services: unknown[] }
|
|
49
|
-
expect(Array.isArray(help.elements)).toBe(true)
|
|
50
|
-
expect(help.elements.length).toBeGreaterThan(50)
|
|
51
|
-
|
|
52
|
-
skill.remove()
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('`window.schmancy.help("schmancy-button")` returns attribute enum values', async () => {
|
|
56
|
-
const skill = document.createElement('schmancy-skill')
|
|
57
|
-
document.body.appendChild(skill)
|
|
58
|
-
await customElements.whenDefined('schmancy-skill')
|
|
59
|
-
await new Promise(requestAnimationFrame)
|
|
60
|
-
|
|
61
|
-
const btn = window.schmancy!.help('schmancy-button') as {
|
|
62
|
-
attributes?: Array<{ name: string; values?: string[] }>
|
|
63
|
-
}
|
|
64
|
-
expect(btn).toBeTruthy()
|
|
65
|
-
expect(btn.attributes?.length ?? 0).toBeGreaterThan(0)
|
|
66
|
-
const variant = btn.attributes?.find(a => a.name === 'variant')
|
|
67
|
-
expect(variant?.values).toContain('filled')
|
|
68
|
-
|
|
69
|
-
skill.remove()
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('`window.schmancy.capabilities()` reports every probed feature', async () => {
|
|
73
|
-
const skill = document.createElement('schmancy-skill')
|
|
74
|
-
document.body.appendChild(skill)
|
|
75
|
-
await customElements.whenDefined('schmancy-skill')
|
|
76
|
-
await new Promise(requestAnimationFrame)
|
|
77
|
-
|
|
78
|
-
const caps = window.schmancy!.capabilities()
|
|
79
|
-
expect(caps).toMatchObject({
|
|
80
|
-
popover: expect.any(Boolean),
|
|
81
|
-
declarativeShadowDom: expect.any(Boolean),
|
|
82
|
-
scopedRegistries: expect.any(Boolean),
|
|
83
|
-
trustedTypes: expect.any(Boolean),
|
|
84
|
-
cssRegisteredProperties: expect.any(Boolean),
|
|
85
|
-
elementInternalsAria: expect.any(Boolean),
|
|
86
|
-
formAssociated: expect.any(Boolean),
|
|
87
|
-
adoptedStyleSheets: expect.any(Boolean),
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
skill.remove()
|
|
91
|
-
})
|
|
92
|
-
})
|
package/src/agent/helpers.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import manifest from 'virtual:schmancy-manifest'
|
|
2
|
-
|
|
3
|
-
export type ElementEntry = {
|
|
4
|
-
kind: 'class'
|
|
5
|
-
name: string
|
|
6
|
-
tagName?: string
|
|
7
|
-
description?: string
|
|
8
|
-
summary?: string
|
|
9
|
-
attributes?: Array<{
|
|
10
|
-
name: string
|
|
11
|
-
description?: string
|
|
12
|
-
type?: { text?: string }
|
|
13
|
-
default?: string
|
|
14
|
-
values?: string[]
|
|
15
|
-
}>
|
|
16
|
-
events?: Array<{ name: string; description?: string; type?: { text?: string } }>
|
|
17
|
-
slots?: Array<{ name: string; description?: string }>
|
|
18
|
-
cssProperties?: Array<{ name: string; description?: string }>
|
|
19
|
-
cssParts?: Array<{ name: string; description?: string }>
|
|
20
|
-
whenToUse?: string
|
|
21
|
-
platformPrimitive?: { tag: string; mode?: string; note?: string }
|
|
22
|
-
contexts?: { provides?: string[]; consumes?: string[] }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type ServiceEntry = {
|
|
26
|
-
kind: 'variable'
|
|
27
|
-
name: string
|
|
28
|
-
description?: string
|
|
29
|
-
summary?: string
|
|
30
|
-
service: true
|
|
31
|
-
methods?: Array<{ signature: string; summary?: string }>
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type Declaration = ElementEntry | ServiceEntry | { kind: string; name: string; [key: string]: unknown }
|
|
35
|
-
|
|
36
|
-
function allDeclarations(): Declaration[] {
|
|
37
|
-
const out: Declaration[] = []
|
|
38
|
-
for (const mod of manifest.modules ?? []) {
|
|
39
|
-
const decls = (mod as unknown as { declarations?: Declaration[] }).declarations ?? []
|
|
40
|
-
for (const decl of decls) out.push(decl)
|
|
41
|
-
}
|
|
42
|
-
return out
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function elements(): ElementEntry[] {
|
|
46
|
-
return allDeclarations().filter(
|
|
47
|
-
(d): d is ElementEntry => d.kind === 'class' && typeof (d as ElementEntry).tagName === 'string',
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function services(): ServiceEntry[] {
|
|
52
|
-
return allDeclarations().filter((d): d is ServiceEntry => d.kind === 'variable' && (d as ServiceEntry).service === true)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function help(tag?: string): unknown {
|
|
56
|
-
if (!tag) {
|
|
57
|
-
return {
|
|
58
|
-
elements: elements().map(e => ({ tag: e.tagName, summary: e.summary ?? e.description })),
|
|
59
|
-
services: services().map(s => ({ name: s.name, summary: s.summary ?? s.description })),
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const el = elements().find(e => e.tagName === tag)
|
|
63
|
-
if (el) return el
|
|
64
|
-
const svc = services().find(s => s.name === tag)
|
|
65
|
-
if (svc) return svc
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function tokens(): string[] {
|
|
70
|
-
return (manifest as { tokens?: string[] }).tokens ?? []
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function platformPrimitive(tag: string): ElementEntry['platformPrimitive'] | null {
|
|
74
|
-
return elements().find(e => e.tagName === tag)?.platformPrimitive ?? null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function registeredTags(): string[] {
|
|
78
|
-
return elements()
|
|
79
|
-
.map(e => e.tagName!)
|
|
80
|
-
.filter(tag => typeof customElements.get(tag) !== 'undefined')
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function a11yAudit(): Array<{
|
|
84
|
-
tag: string
|
|
85
|
-
role: string | null
|
|
86
|
-
ariaLabel: string | null
|
|
87
|
-
hasShadowRoot: boolean
|
|
88
|
-
formAssociated: boolean
|
|
89
|
-
}> {
|
|
90
|
-
const tags = new Set(elements().map(e => e.tagName!))
|
|
91
|
-
const report: Array<{
|
|
92
|
-
tag: string
|
|
93
|
-
role: string | null
|
|
94
|
-
ariaLabel: string | null
|
|
95
|
-
hasShadowRoot: boolean
|
|
96
|
-
formAssociated: boolean
|
|
97
|
-
}> = []
|
|
98
|
-
const all = document.querySelectorAll('*')
|
|
99
|
-
for (const node of Array.from(all)) {
|
|
100
|
-
const tag = node.tagName.toLowerCase()
|
|
101
|
-
if (!tags.has(tag)) continue
|
|
102
|
-
const ctor = customElements.get(tag) as (CustomElementConstructor & { formAssociated?: boolean }) | undefined
|
|
103
|
-
report.push({
|
|
104
|
-
tag,
|
|
105
|
-
role: node.getAttribute('role'),
|
|
106
|
-
ariaLabel: node.getAttribute('aria-label'),
|
|
107
|
-
hasShadowRoot: Boolean((node as Element & { shadowRoot?: ShadowRoot | null }).shadowRoot),
|
|
108
|
-
formAssociated: Boolean(ctor?.formAssociated),
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
return report
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export type Capabilities = {
|
|
115
|
-
popover: boolean
|
|
116
|
-
declarativeShadowDom: boolean
|
|
117
|
-
scopedRegistries: boolean
|
|
118
|
-
trustedTypes: boolean
|
|
119
|
-
cssRegisteredProperties: boolean
|
|
120
|
-
elementInternalsAria: boolean
|
|
121
|
-
formAssociated: boolean
|
|
122
|
-
adoptedStyleSheets: boolean
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Runtime feature probe. Tells an agent which platform capabilities the
|
|
127
|
-
* current sandbox exposes, so it can adapt without assuming the sandbox CSP
|
|
128
|
-
* or browser version. Every check is feature-detect, not UA-sniff.
|
|
129
|
-
*/
|
|
130
|
-
export function capabilities(): Capabilities {
|
|
131
|
-
const anyTemplate = typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement.prototype : null
|
|
132
|
-
const anyElInternals = typeof ElementInternals !== 'undefined' ? ElementInternals.prototype : null
|
|
133
|
-
return {
|
|
134
|
-
popover: typeof HTMLElement !== 'undefined' && 'popover' in HTMLElement.prototype,
|
|
135
|
-
declarativeShadowDom: Boolean(anyTemplate && 'shadowRootMode' in anyTemplate),
|
|
136
|
-
scopedRegistries: (() => {
|
|
137
|
-
try {
|
|
138
|
-
// Native scoped registries require a constructible CustomElementRegistry.
|
|
139
|
-
// Pre-Safari-26/Chrome-146, the constructor throws Illegal constructor.
|
|
140
|
-
void new (window as { CustomElementRegistry?: new () => unknown }).CustomElementRegistry!()
|
|
141
|
-
return true
|
|
142
|
-
} catch {
|
|
143
|
-
return false
|
|
144
|
-
}
|
|
145
|
-
})(),
|
|
146
|
-
trustedTypes: typeof (globalThis as { trustedTypes?: unknown }).trustedTypes !== 'undefined',
|
|
147
|
-
cssRegisteredProperties: typeof (window as { CSS?: { registerProperty?: unknown } }).CSS?.registerProperty === 'function',
|
|
148
|
-
elementInternalsAria: Boolean(anyElInternals && 'role' in anyElInternals),
|
|
149
|
-
formAssociated: typeof ElementInternals !== 'undefined',
|
|
150
|
-
adoptedStyleSheets: typeof Document !== 'undefined' && 'adoptedStyleSheets' in Document.prototype,
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export function manifestUrl(): string {
|
|
155
|
-
const blob = new Blob([JSON.stringify(manifest)], { type: 'application/json' })
|
|
156
|
-
return URL.createObjectURL(blob)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export { manifest }
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { SchmancyElement } from '../../mixins/index'
|
|
2
|
-
import { html } from 'lit'
|
|
3
|
-
import { customElement } from 'lit/decorators.js'
|
|
4
|
-
import {
|
|
5
|
-
a11yAudit,
|
|
6
|
-
capabilities,
|
|
7
|
-
help,
|
|
8
|
-
manifest,
|
|
9
|
-
manifestUrl,
|
|
10
|
-
platformPrimitive,
|
|
11
|
-
registeredTags,
|
|
12
|
-
tokens,
|
|
13
|
-
} from './helpers'
|
|
14
|
-
|
|
15
|
-
declare global {
|
|
16
|
-
interface Window {
|
|
17
|
-
schmancy?: {
|
|
18
|
-
manifest: typeof manifest
|
|
19
|
-
manifestUrl: string
|
|
20
|
-
help: typeof help
|
|
21
|
-
tokens: typeof tokens
|
|
22
|
-
platformPrimitive: typeof platformPrimitive
|
|
23
|
-
registeredTags: typeof registeredTags
|
|
24
|
-
a11yAudit: typeof a11yAudit
|
|
25
|
-
capabilities: typeof capabilities
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let installedUrl: string | null = null
|
|
31
|
-
|
|
32
|
-
function install() {
|
|
33
|
-
if (typeof window === 'undefined') return
|
|
34
|
-
if (installedUrl) return
|
|
35
|
-
installedUrl = manifestUrl()
|
|
36
|
-
window.schmancy = {
|
|
37
|
-
manifest,
|
|
38
|
-
manifestUrl: installedUrl,
|
|
39
|
-
help,
|
|
40
|
-
tokens,
|
|
41
|
-
platformPrimitive,
|
|
42
|
-
registeredTags,
|
|
43
|
-
a11yAudit,
|
|
44
|
-
capabilities,
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Self-describing runtime helper. Drop `<schmancy-skill></schmancy-skill>`
|
|
50
|
-
* once on a page and `window.schmancy.help('schmancy-button')` returns the
|
|
51
|
-
* machine-readable entry for any tag. Renders nothing.
|
|
52
|
-
*
|
|
53
|
-
* @element schmancy-skill
|
|
54
|
-
*/
|
|
55
|
-
@customElement('schmancy-skill')
|
|
56
|
-
export class SchmancySkill extends SchmancyElement {
|
|
57
|
-
connectedCallback() {
|
|
58
|
-
super.connectedCallback()
|
|
59
|
-
install()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
render() {
|
|
63
|
-
return html``
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
declare global {
|
|
68
|
-
interface HTMLElementTagNameMap {
|
|
69
|
-
'schmancy-skill': SchmancySkill
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
declare module 'virtual:schmancy-manifest' {
|
|
2
|
-
type ManifestModule = { kind: 'javascript-module'; path: string; declarations: Array<Record<string, unknown>> }
|
|
3
|
-
const manifest: {
|
|
4
|
-
schemaVersion: '1.0.0'
|
|
5
|
-
readme?: string
|
|
6
|
-
modules: ManifestModule[]
|
|
7
|
-
tokens: string[]
|
|
8
|
-
}
|
|
9
|
-
export default manifest
|
|
10
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import manifest from 'virtual:schmancy-manifest';
|
|
2
|
-
export type ElementEntry = {
|
|
3
|
-
kind: 'class';
|
|
4
|
-
name: string;
|
|
5
|
-
tagName?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
summary?: string;
|
|
8
|
-
attributes?: Array<{
|
|
9
|
-
name: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
type?: {
|
|
12
|
-
text?: string;
|
|
13
|
-
};
|
|
14
|
-
default?: string;
|
|
15
|
-
values?: string[];
|
|
16
|
-
}>;
|
|
17
|
-
events?: Array<{
|
|
18
|
-
name: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
type?: {
|
|
21
|
-
text?: string;
|
|
22
|
-
};
|
|
23
|
-
}>;
|
|
24
|
-
slots?: Array<{
|
|
25
|
-
name: string;
|
|
26
|
-
description?: string;
|
|
27
|
-
}>;
|
|
28
|
-
cssProperties?: Array<{
|
|
29
|
-
name: string;
|
|
30
|
-
description?: string;
|
|
31
|
-
}>;
|
|
32
|
-
cssParts?: Array<{
|
|
33
|
-
name: string;
|
|
34
|
-
description?: string;
|
|
35
|
-
}>;
|
|
36
|
-
whenToUse?: string;
|
|
37
|
-
platformPrimitive?: {
|
|
38
|
-
tag: string;
|
|
39
|
-
mode?: string;
|
|
40
|
-
note?: string;
|
|
41
|
-
};
|
|
42
|
-
contexts?: {
|
|
43
|
-
provides?: string[];
|
|
44
|
-
consumes?: string[];
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
export type ServiceEntry = {
|
|
48
|
-
kind: 'variable';
|
|
49
|
-
name: string;
|
|
50
|
-
description?: string;
|
|
51
|
-
summary?: string;
|
|
52
|
-
service: true;
|
|
53
|
-
methods?: Array<{
|
|
54
|
-
signature: string;
|
|
55
|
-
summary?: string;
|
|
56
|
-
}>;
|
|
57
|
-
};
|
|
58
|
-
export declare function help(tag?: string): unknown;
|
|
59
|
-
export declare function tokens(): string[];
|
|
60
|
-
export declare function platformPrimitive(tag: string): ElementEntry['platformPrimitive'] | null;
|
|
61
|
-
export declare function registeredTags(): string[];
|
|
62
|
-
export declare function a11yAudit(): Array<{
|
|
63
|
-
tag: string;
|
|
64
|
-
role: string | null;
|
|
65
|
-
ariaLabel: string | null;
|
|
66
|
-
hasShadowRoot: boolean;
|
|
67
|
-
formAssociated: boolean;
|
|
68
|
-
}>;
|
|
69
|
-
export type Capabilities = {
|
|
70
|
-
popover: boolean;
|
|
71
|
-
declarativeShadowDom: boolean;
|
|
72
|
-
scopedRegistries: boolean;
|
|
73
|
-
trustedTypes: boolean;
|
|
74
|
-
cssRegisteredProperties: boolean;
|
|
75
|
-
elementInternalsAria: boolean;
|
|
76
|
-
formAssociated: boolean;
|
|
77
|
-
adoptedStyleSheets: boolean;
|
|
78
|
-
};
|
|
79
|
-
/**
|
|
80
|
-
* Runtime feature probe. Tells an agent which platform capabilities the
|
|
81
|
-
* current sandbox exposes, so it can adapt without assuming the sandbox CSP
|
|
82
|
-
* or browser version. Every check is feature-detect, not UA-sniff.
|
|
83
|
-
*/
|
|
84
|
-
export declare function capabilities(): Capabilities;
|
|
85
|
-
export declare function manifestUrl(): string;
|
|
86
|
-
export { manifest };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { SchmancyElement } from '../../mixins/index';
|
|
2
|
-
import { a11yAudit, capabilities, help, manifest, platformPrimitive, registeredTags, tokens } from './helpers';
|
|
3
|
-
declare global {
|
|
4
|
-
interface Window {
|
|
5
|
-
schmancy?: {
|
|
6
|
-
manifest: typeof manifest;
|
|
7
|
-
manifestUrl: string;
|
|
8
|
-
help: typeof help;
|
|
9
|
-
tokens: typeof tokens;
|
|
10
|
-
platformPrimitive: typeof platformPrimitive;
|
|
11
|
-
registeredTags: typeof registeredTags;
|
|
12
|
-
a11yAudit: typeof a11yAudit;
|
|
13
|
-
capabilities: typeof capabilities;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Self-describing runtime helper. Drop `<schmancy-skill></schmancy-skill>`
|
|
19
|
-
* once on a page and `window.schmancy.help('schmancy-button')` returns the
|
|
20
|
-
* machine-readable entry for any tag. Renders nothing.
|
|
21
|
-
*
|
|
22
|
-
* @element schmancy-skill
|
|
23
|
-
*/
|
|
24
|
-
export declare class SchmancySkill extends SchmancyElement {
|
|
25
|
-
connectedCallback(): void;
|
|
26
|
-
render(): import("lit-html").TemplateResult<1>;
|
|
27
|
-
}
|
|
28
|
-
declare global {
|
|
29
|
-
interface HTMLElementTagNameMap {
|
|
30
|
-
'schmancy-skill': SchmancySkill;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
File without changes
|