@mhmo91/schmancy 0.9.4 → 0.9.5
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 +13 -0
- package/README.md +14 -4
- package/dist/.claude-plugin/plugin.json +13 -0
- package/dist/skills/SKILL.md +120 -0
- package/dist/skills/schmancy/SKILL.md +120 -0
- package/package.json +3 -3
- package/skills/schmancy/INDEX.md +72 -0
- package/skills/schmancy/SKILL.md +120 -0
- package/skills/schmancy/animation.md +64 -0
- package/skills/schmancy/area.md +141 -0
- package/skills/schmancy/audio.md +69 -0
- package/skills/schmancy/autocomplete.md +53 -0
- package/skills/schmancy/avatar.md +47 -0
- package/skills/schmancy/badge.md +41 -0
- package/skills/schmancy/boat.md +47 -0
- package/skills/schmancy/busy.md +36 -0
- package/skills/schmancy/button.md +59 -0
- package/skills/schmancy/card.md +53 -0
- package/skills/schmancy/charts.md +93 -0
- package/skills/schmancy/checkbox.md +36 -0
- package/skills/schmancy/chips.md +87 -0
- package/skills/schmancy/code-highlight.md +47 -0
- package/skills/schmancy/connectivity.md +36 -0
- package/skills/schmancy/content-drawer.md +65 -0
- package/skills/schmancy/date-range-inline.md +44 -0
- package/skills/schmancy/date-range.md +50 -0
- package/skills/schmancy/delay.md +50 -0
- package/skills/schmancy/details.md +66 -0
- package/skills/schmancy/dialog.md +69 -0
- package/skills/schmancy/directives.md +298 -0
- package/skills/schmancy/discovery.md +67 -0
- package/skills/schmancy/divider.md +31 -0
- package/skills/schmancy/dropdown.md +47 -0
- package/skills/schmancy/expand.md +63 -0
- package/skills/schmancy/extra.md +59 -0
- package/skills/schmancy/float.md +14 -0
- package/skills/schmancy/form.md +49 -0
- package/skills/schmancy/icons.md +44 -0
- package/skills/schmancy/iframe.md +44 -0
- package/skills/schmancy/input.md +56 -0
- package/skills/schmancy/json.md +33 -0
- package/skills/schmancy/layout.md +63 -0
- package/skills/schmancy/lightbox.md +36 -0
- package/skills/schmancy/list.md +67 -0
- package/skills/schmancy/mailbox.md +102 -0
- package/skills/schmancy/map.md +55 -0
- package/skills/schmancy/menu.md +39 -0
- package/skills/schmancy/mixins.md +99 -0
- package/skills/schmancy/nav-drawer.md +52 -0
- package/skills/schmancy/navigation-bar.md +48 -0
- package/skills/schmancy/navigation-rail.md +62 -0
- package/skills/schmancy/notification.md +60 -0
- package/skills/schmancy/option.md +43 -0
- package/skills/schmancy/page.md +42 -0
- package/skills/schmancy/progress.md +30 -0
- package/skills/schmancy/qr-scanner.md +51 -0
- package/skills/schmancy/radio-group.md +50 -0
- package/skills/schmancy/range.md +47 -0
- package/skills/schmancy/rxjs-utils.md +60 -0
- package/skills/schmancy/select.md +49 -0
- package/skills/schmancy/sheet.md +76 -0
- package/skills/schmancy/slider.md +43 -0
- package/skills/schmancy/steps.md +53 -0
- package/skills/schmancy/store.md +126 -0
- package/skills/schmancy/surface.md +86 -0
- package/skills/schmancy/table.md +60 -0
- package/skills/schmancy/tabs.md +49 -0
- package/skills/schmancy/teleport.md +55 -0
- package/skills/schmancy/textarea.md +48 -0
- package/skills/schmancy/theme-button.md +26 -0
- package/skills/schmancy/theme.md +58 -0
- package/skills/schmancy/tooltip.md +38 -0
- package/skills/schmancy/tree.md +53 -0
- package/skills/schmancy/typewriter.md +46 -0
- package/skills/schmancy/typography.md +53 -0
- package/skills/schmancy/utils.md +95 -0
- package/skills/schmancy/window.md +67 -0
- /package/{ai → dist/skills}/INDEX.md +0 -0
- /package/{ai → dist/skills}/animation.md +0 -0
- /package/{ai → dist/skills}/area.md +0 -0
- /package/{ai → dist/skills}/audio.md +0 -0
- /package/{ai → dist/skills}/autocomplete.md +0 -0
- /package/{ai → dist/skills}/avatar.md +0 -0
- /package/{ai → dist/skills}/badge.md +0 -0
- /package/{ai → dist/skills}/boat.md +0 -0
- /package/{ai → dist/skills}/busy.md +0 -0
- /package/{ai → dist/skills}/button.md +0 -0
- /package/{ai → dist/skills}/card.md +0 -0
- /package/{ai → dist/skills}/charts.md +0 -0
- /package/{ai → dist/skills}/checkbox.md +0 -0
- /package/{ai → dist/skills}/chips.md +0 -0
- /package/{ai → dist/skills}/code-highlight.md +0 -0
- /package/{ai → dist/skills}/connectivity.md +0 -0
- /package/{ai → dist/skills}/content-drawer.md +0 -0
- /package/{ai → dist/skills}/date-range-inline.md +0 -0
- /package/{ai → dist/skills}/date-range.md +0 -0
- /package/{ai → dist/skills}/delay.md +0 -0
- /package/{ai → dist/skills}/details.md +0 -0
- /package/{ai → dist/skills}/dialog.md +0 -0
- /package/{ai → dist/skills}/directives.md +0 -0
- /package/{ai → dist/skills}/discovery.md +0 -0
- /package/{ai → dist/skills}/divider.md +0 -0
- /package/{ai → dist/skills}/dropdown.md +0 -0
- /package/{ai → dist/skills}/expand.md +0 -0
- /package/{ai → dist/skills}/extra.md +0 -0
- /package/{ai → dist/skills}/float.md +0 -0
- /package/{ai → dist/skills}/form.md +0 -0
- /package/{ai → dist/skills}/icons.md +0 -0
- /package/{ai → dist/skills}/iframe.md +0 -0
- /package/{ai → dist/skills}/input.md +0 -0
- /package/{ai → dist/skills}/json.md +0 -0
- /package/{ai → dist/skills}/layout.md +0 -0
- /package/{ai → dist/skills}/lightbox.md +0 -0
- /package/{ai → dist/skills}/list.md +0 -0
- /package/{ai → dist/skills}/mailbox.md +0 -0
- /package/{ai → dist/skills}/map.md +0 -0
- /package/{ai → dist/skills}/menu.md +0 -0
- /package/{ai → dist/skills}/mixins.md +0 -0
- /package/{ai → dist/skills}/nav-drawer.md +0 -0
- /package/{ai → dist/skills}/navigation-bar.md +0 -0
- /package/{ai → dist/skills}/navigation-rail.md +0 -0
- /package/{ai → dist/skills}/notification.md +0 -0
- /package/{ai → dist/skills}/option.md +0 -0
- /package/{ai → dist/skills}/page.md +0 -0
- /package/{ai → dist/skills}/progress.md +0 -0
- /package/{ai → dist/skills}/qr-scanner.md +0 -0
- /package/{ai → dist/skills}/radio-group.md +0 -0
- /package/{ai → dist/skills}/range.md +0 -0
- /package/{ai → dist/skills}/rxjs-utils.md +0 -0
- /package/dist/{ai → skills/schmancy}/INDEX.md +0 -0
- /package/dist/{ai → skills/schmancy}/animation.md +0 -0
- /package/dist/{ai → skills/schmancy}/area.md +0 -0
- /package/dist/{ai → skills/schmancy}/audio.md +0 -0
- /package/dist/{ai → skills/schmancy}/autocomplete.md +0 -0
- /package/dist/{ai → skills/schmancy}/avatar.md +0 -0
- /package/dist/{ai → skills/schmancy}/badge.md +0 -0
- /package/dist/{ai → skills/schmancy}/boat.md +0 -0
- /package/dist/{ai → skills/schmancy}/busy.md +0 -0
- /package/dist/{ai → skills/schmancy}/button.md +0 -0
- /package/dist/{ai → skills/schmancy}/card.md +0 -0
- /package/dist/{ai → skills/schmancy}/charts.md +0 -0
- /package/dist/{ai → skills/schmancy}/checkbox.md +0 -0
- /package/dist/{ai → skills/schmancy}/chips.md +0 -0
- /package/dist/{ai → skills/schmancy}/code-highlight.md +0 -0
- /package/dist/{ai → skills/schmancy}/connectivity.md +0 -0
- /package/dist/{ai → skills/schmancy}/content-drawer.md +0 -0
- /package/dist/{ai → skills/schmancy}/date-range-inline.md +0 -0
- /package/dist/{ai → skills/schmancy}/date-range.md +0 -0
- /package/dist/{ai → skills/schmancy}/delay.md +0 -0
- /package/dist/{ai → skills/schmancy}/details.md +0 -0
- /package/dist/{ai → skills/schmancy}/dialog.md +0 -0
- /package/dist/{ai → skills/schmancy}/directives.md +0 -0
- /package/dist/{ai → skills/schmancy}/discovery.md +0 -0
- /package/dist/{ai → skills/schmancy}/divider.md +0 -0
- /package/dist/{ai → skills/schmancy}/dropdown.md +0 -0
- /package/dist/{ai → skills/schmancy}/expand.md +0 -0
- /package/dist/{ai → skills/schmancy}/extra.md +0 -0
- /package/dist/{ai → skills/schmancy}/float.md +0 -0
- /package/dist/{ai → skills/schmancy}/form.md +0 -0
- /package/dist/{ai → skills/schmancy}/icons.md +0 -0
- /package/dist/{ai → skills/schmancy}/iframe.md +0 -0
- /package/dist/{ai → skills/schmancy}/input.md +0 -0
- /package/dist/{ai → skills/schmancy}/json.md +0 -0
- /package/dist/{ai → skills/schmancy}/layout.md +0 -0
- /package/dist/{ai → skills/schmancy}/lightbox.md +0 -0
- /package/dist/{ai → skills/schmancy}/list.md +0 -0
- /package/dist/{ai → skills/schmancy}/mailbox.md +0 -0
- /package/dist/{ai → skills/schmancy}/map.md +0 -0
- /package/dist/{ai → skills/schmancy}/menu.md +0 -0
- /package/dist/{ai → skills/schmancy}/mixins.md +0 -0
- /package/dist/{ai → skills/schmancy}/nav-drawer.md +0 -0
- /package/dist/{ai → skills/schmancy}/navigation-bar.md +0 -0
- /package/dist/{ai → skills/schmancy}/navigation-rail.md +0 -0
- /package/dist/{ai → skills/schmancy}/notification.md +0 -0
- /package/dist/{ai → skills/schmancy}/option.md +0 -0
- /package/dist/{ai → skills/schmancy}/page.md +0 -0
- /package/dist/{ai → skills/schmancy}/progress.md +0 -0
- /package/dist/{ai → skills/schmancy}/qr-scanner.md +0 -0
- /package/dist/{ai → skills/schmancy}/radio-group.md +0 -0
- /package/dist/{ai → skills/schmancy}/range.md +0 -0
- /package/dist/{ai → skills/schmancy}/rxjs-utils.md +0 -0
- /package/{ai → dist/skills/schmancy}/select.md +0 -0
- /package/{ai → dist/skills/schmancy}/sheet.md +0 -0
- /package/{ai → dist/skills/schmancy}/slider.md +0 -0
- /package/{ai → dist/skills/schmancy}/steps.md +0 -0
- /package/{ai → dist/skills/schmancy}/store.md +0 -0
- /package/{ai → dist/skills/schmancy}/surface.md +0 -0
- /package/{ai → dist/skills/schmancy}/table.md +0 -0
- /package/{ai → dist/skills/schmancy}/tabs.md +0 -0
- /package/{ai → dist/skills/schmancy}/teleport.md +0 -0
- /package/{ai → dist/skills/schmancy}/textarea.md +0 -0
- /package/{ai → dist/skills/schmancy}/theme-button.md +0 -0
- /package/{ai → dist/skills/schmancy}/theme.md +0 -0
- /package/{ai → dist/skills/schmancy}/tooltip.md +0 -0
- /package/{ai → dist/skills/schmancy}/tree.md +0 -0
- /package/{ai → dist/skills/schmancy}/typewriter.md +0 -0
- /package/{ai → dist/skills/schmancy}/typography.md +0 -0
- /package/{ai → dist/skills/schmancy}/utils.md +0 -0
- /package/{ai → dist/skills/schmancy}/window.md +0 -0
- /package/dist/{ai → skills}/select.md +0 -0
- /package/dist/{ai → skills}/sheet.md +0 -0
- /package/dist/{ai → skills}/slider.md +0 -0
- /package/dist/{ai → skills}/steps.md +0 -0
- /package/dist/{ai → skills}/store.md +0 -0
- /package/dist/{ai → skills}/surface.md +0 -0
- /package/dist/{ai → skills}/table.md +0 -0
- /package/dist/{ai → skills}/tabs.md +0 -0
- /package/dist/{ai → skills}/teleport.md +0 -0
- /package/dist/{ai → skills}/textarea.md +0 -0
- /package/dist/{ai → skills}/theme-button.md +0 -0
- /package/dist/{ai → skills}/theme.md +0 -0
- /package/dist/{ai → skills}/tooltip.md +0 -0
- /package/dist/{ai → skills}/tree.md +0 -0
- /package/dist/{ai → skills}/typewriter.md +0 -0
- /package/dist/{ai → skills}/typography.md +0 -0
- /package/dist/{ai → skills}/utils.md +0 -0
- /package/dist/{ai → skills}/window.md +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "schmancy",
|
|
3
|
+
"description": "Claude Code support for the @mhmo91/schmancy web-component UI library. Provides foundations (routing, store, base class, theme, directives), component API lookup for 60+ tags, and overlay service patterns ($dialog, $notify, schmancyContentDrawer).",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "samwaai",
|
|
7
|
+
"url": "https://github.com/samwaai"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/samwaai/schmancy",
|
|
10
|
+
"repository": "https://github.com/samwaai/schmancy",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": ["lit", "web-components", "ui", "schmancy", "tailwind", "rxjs"]
|
|
13
|
+
}
|
package/README.md
CHANGED
|
@@ -13,6 +13,16 @@ import '@mhmo91/schmancy'
|
|
|
13
13
|
import { magnetic, cursorGlow, gravity } from '@mhmo91/schmancy/directives'
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
## Use with Claude Code
|
|
17
|
+
|
|
18
|
+
Schmancy ships a Claude Code plugin. In any Claude Code session, run:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
/plugin install https://github.com/samwaai/schmancy
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Claude now knows every Schmancy component, foundation pattern, and convention in your project. The skill activates automatically when you work on schmancy code — no CLAUDE.md edits, no symlinks.
|
|
25
|
+
|
|
16
26
|
## Quick Start
|
|
17
27
|
|
|
18
28
|
```html
|
|
@@ -38,12 +48,12 @@ import { magnetic, cursorGlow, gravity } from '@mhmo91/schmancy/directives'
|
|
|
38
48
|
|
|
39
49
|
Schmancy is organized in four layers:
|
|
40
50
|
|
|
41
|
-
- **Foundations** — [Area](./
|
|
42
|
-
- **Atoms** — [Typography](./
|
|
51
|
+
- **Foundations** — [Area](./skills/schmancy/area.md) · [Store](./skills/schmancy/store.md) · [Mixins ($LitElement)](./skills/schmancy/mixins.md) · [Theme](./skills/schmancy/theme.md) · [Directives](./skills/schmancy/directives.md)
|
|
52
|
+
- **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)
|
|
43
53
|
- **Composites (by job)** — Forms, Navigation, Overlays, Interaction, Feedback, Display
|
|
44
|
-
- **Utilities** — [Animation](./
|
|
54
|
+
- **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)
|
|
45
55
|
|
|
46
|
-
**Full component index:** [
|
|
56
|
+
**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.
|
|
47
57
|
|
|
48
58
|
## Tech Stack
|
|
49
59
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "schmancy",
|
|
3
|
+
"description": "Claude Code support for the @mhmo91/schmancy web-component UI library. Provides foundations (routing, store, base class, theme, directives), component API lookup for 60+ tags, and overlay service patterns ($dialog, $notify, schmancyContentDrawer).",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "samwaai",
|
|
7
|
+
"url": "https://github.com/samwaai"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/samwaai/schmancy",
|
|
10
|
+
"repository": "https://github.com/samwaai/schmancy",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": ["lit", "web-components", "ui", "schmancy", "tailwind", "rxjs"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: schmancy
|
|
3
|
+
description: UI patterns, component APIs, and conventions for the @mhmo91/schmancy web-component library (Lit + RxJS + Tailwind). Activate whenever the user works on any <schmancy-*> tag, routing with schmancy-area, state with createContext/@select, the $LitElement base class, theme, directives, or overlay services ($dialog, $notify, schmancyContentDrawer, sheet).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Schmancy
|
|
7
|
+
|
|
8
|
+
Web-component UI library on Lit + RxJS + Tailwind CSS. This skill bundles the full library reference as supporting files alongside this SKILL.md.
|
|
9
|
+
|
|
10
|
+
## How to use this skill
|
|
11
|
+
|
|
12
|
+
All reference files live in this directory. Read by filename.
|
|
13
|
+
|
|
14
|
+
1. **Start with `INDEX.md`** for the full catalog organized by job (foundations / atoms / forms / navigation / overlays / interaction / feedback / display).
|
|
15
|
+
2. **Before writing any `<schmancy-X>` tag**, read `X.md`. Example: `<schmancy-button>` → `button.md`.
|
|
16
|
+
3. **Before editing foundations** (routing, state, base class, theme), read the matching foundation file below.
|
|
17
|
+
4. **Apply the conventions** at the end of this file.
|
|
18
|
+
|
|
19
|
+
## Foundations (the framework pieces — touch first)
|
|
20
|
+
|
|
21
|
+
| Piece | Read |
|
|
22
|
+
|-------|------|
|
|
23
|
+
| Routing (`<schmancy-area>`, `<schmancy-route>`, `area.push()`, `lazy()`) | `area.md` |
|
|
24
|
+
| State (`createContext`, `@select`, `@selectItem`) | `store.md` |
|
|
25
|
+
| Base class (`$LitElement`) | `mixins.md` |
|
|
26
|
+
| Theme (`<schmancy-theme>`, `theme` service) | `theme.md` |
|
|
27
|
+
| Directives (`magnetic`, `cursorGlow`, `gravity`, `reveal`, `animateText`, …) | `directives.md` |
|
|
28
|
+
| Spring physics presets | `animation.md` |
|
|
29
|
+
|
|
30
|
+
## Overlay services (prefer over tags)
|
|
31
|
+
|
|
32
|
+
For modals, toasts, sheets, side drawers — reach for the **imperative service API** first:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { $dialog, $notify, schmancyContentDrawer, sheet, SchmancySheetPosition } from '@mhmo91/schmancy'
|
|
36
|
+
|
|
37
|
+
$dialog.component(new EditForm()) // modal
|
|
38
|
+
$dialog.component(new QuickPicker(), { position: e }) // anchored modal
|
|
39
|
+
$notify.success('Saved'); $notify.error('Failed') // toast
|
|
40
|
+
schmancyContentDrawer.open({ component: new Detail() }) // side panel
|
|
41
|
+
sheet.open({ component: new Picker(), position: SchmancySheetPosition.BOTTOM }) // bottom sheet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
References: `dialog.md`, `notification.md`, `content-drawer.md`, `sheet.md`.
|
|
45
|
+
|
|
46
|
+
Use component tags (`<schmancy-menu>`, `<schmancy-dropdown>`, `<schmancy-tooltip>`, `<schmancy-lightbox>`, `<schmancy-expand>`) only when the tag is the natural fit (anchored panels, tooltips, galleries).
|
|
47
|
+
|
|
48
|
+
## Non-negotiable conventions
|
|
49
|
+
|
|
50
|
+
**Component authoring**
|
|
51
|
+
- Every component extends `$LitElement(style?)`. Never raw `LitElement`.
|
|
52
|
+
- Every RxJS subscription ends with `.pipe(takeUntil(this.disconnecting))`.
|
|
53
|
+
- Register the tag in `HTMLElementTagNameMap` for TypeScript.
|
|
54
|
+
|
|
55
|
+
**State**
|
|
56
|
+
- Contexts live at module scope. Many small contexts beat one monolith.
|
|
57
|
+
- Gate subscriptions with `filter(() => ctx.ready)` when reading persisted contexts.
|
|
58
|
+
- Storage tiers: `'memory'` (regenerable) · `'session'` (per-tab) · `'local'` (user prefs) · `'indexeddb'` (>100-entry collections).
|
|
59
|
+
|
|
60
|
+
**Routing**
|
|
61
|
+
- Route guards are `Observable<boolean>`, never cached booleans.
|
|
62
|
+
- `when="tag-name"` must exactly match `@customElement('tag-name')`.
|
|
63
|
+
- Lazy-load route components: `lazy(() => import('./page'))`.
|
|
64
|
+
- After auth/permission guards, use `historyStrategy: 'replace'` or `'pop'` — never `'push'`.
|
|
65
|
+
|
|
66
|
+
**Templates**
|
|
67
|
+
- Lists: `repeat(items, i => i.id, tpl)`. Never `.map()`.
|
|
68
|
+
- View switching: `cache(...)`.
|
|
69
|
+
- Expensive work: `guard([deps], () => expensive())`.
|
|
70
|
+
- Conditionals: `when(...)` / `choose(...)` / `ifDefined(...)`.
|
|
71
|
+
- DOM access: `ref(createRef())`.
|
|
72
|
+
- `classMap(this.classMap({...}))` must be the sole expression in `class=` — never mix with string interpolation.
|
|
73
|
+
|
|
74
|
+
**Styling**
|
|
75
|
+
- Colors: `--schmancy-sys-color-*` CSS vars or Tailwind theme classes. Never hardcoded hex.
|
|
76
|
+
- No `setTimeout` / `setInterval` / `addEventListener` — use RxJS (`timer`, `interval`, `fromEvent`).
|
|
77
|
+
|
|
78
|
+
**Accessibility (combobox forms)**
|
|
79
|
+
```typescript
|
|
80
|
+
role="combobox"
|
|
81
|
+
aria-haspopup="listbox"
|
|
82
|
+
aria-expanded=${this._open}
|
|
83
|
+
aria-controls="listbox-id"
|
|
84
|
+
```
|
|
85
|
+
Plus a live region: `<div id="live-status" role="status" aria-live="polite" class="sr-only"></div>`.
|
|
86
|
+
|
|
87
|
+
## Minimal app skeleton
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
<schmancy-theme root scheme="dark">
|
|
91
|
+
<schmancy-surface type="solid" fill="all">
|
|
92
|
+
<schmancy-scroll>
|
|
93
|
+
<schmancy-area
|
|
94
|
+
name="root"
|
|
95
|
+
.default=${lazy(() => import('./home.page'))}
|
|
96
|
+
>
|
|
97
|
+
<schmancy-route when="home-page"
|
|
98
|
+
.component=${lazy(() => import('./home.page'))}></schmancy-route>
|
|
99
|
+
|
|
100
|
+
<schmancy-route when="app-index"
|
|
101
|
+
.component=${lazy(() => import('./app.page'))}
|
|
102
|
+
.guard=${authState$.pipe(
|
|
103
|
+
map(u => !!u),
|
|
104
|
+
takeUntil(this.disconnecting),
|
|
105
|
+
)}
|
|
106
|
+
@redirect=${() => area.push({
|
|
107
|
+
component: 'home-page', area: 'root', historyStrategy: 'replace',
|
|
108
|
+
})}></schmancy-route>
|
|
109
|
+
</schmancy-area>
|
|
110
|
+
</schmancy-scroll>
|
|
111
|
+
</schmancy-surface>
|
|
112
|
+
</schmancy-theme>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Workflow
|
|
116
|
+
|
|
117
|
+
1. User describes a UI task.
|
|
118
|
+
2. Read `INDEX.md` to find the relevant components or foundations.
|
|
119
|
+
3. Read the specific `.md` files for the APIs involved.
|
|
120
|
+
4. Write code that follows the conventions above.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: schmancy
|
|
3
|
+
description: UI patterns, component APIs, and conventions for the @mhmo91/schmancy web-component library (Lit + RxJS + Tailwind). Activate whenever the user works on any <schmancy-*> tag, routing with schmancy-area, state with createContext/@select, the $LitElement base class, theme, directives, or overlay services ($dialog, $notify, schmancyContentDrawer, sheet).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Schmancy
|
|
7
|
+
|
|
8
|
+
Web-component UI library on Lit + RxJS + Tailwind CSS. This skill bundles the full library reference as supporting files alongside this SKILL.md.
|
|
9
|
+
|
|
10
|
+
## How to use this skill
|
|
11
|
+
|
|
12
|
+
All reference files live in this directory. Read by filename.
|
|
13
|
+
|
|
14
|
+
1. **Start with `INDEX.md`** for the full catalog organized by job (foundations / atoms / forms / navigation / overlays / interaction / feedback / display).
|
|
15
|
+
2. **Before writing any `<schmancy-X>` tag**, read `X.md`. Example: `<schmancy-button>` → `button.md`.
|
|
16
|
+
3. **Before editing foundations** (routing, state, base class, theme), read the matching foundation file below.
|
|
17
|
+
4. **Apply the conventions** at the end of this file.
|
|
18
|
+
|
|
19
|
+
## Foundations (the framework pieces — touch first)
|
|
20
|
+
|
|
21
|
+
| Piece | Read |
|
|
22
|
+
|-------|------|
|
|
23
|
+
| Routing (`<schmancy-area>`, `<schmancy-route>`, `area.push()`, `lazy()`) | `area.md` |
|
|
24
|
+
| State (`createContext`, `@select`, `@selectItem`) | `store.md` |
|
|
25
|
+
| Base class (`$LitElement`) | `mixins.md` |
|
|
26
|
+
| Theme (`<schmancy-theme>`, `theme` service) | `theme.md` |
|
|
27
|
+
| Directives (`magnetic`, `cursorGlow`, `gravity`, `reveal`, `animateText`, …) | `directives.md` |
|
|
28
|
+
| Spring physics presets | `animation.md` |
|
|
29
|
+
|
|
30
|
+
## Overlay services (prefer over tags)
|
|
31
|
+
|
|
32
|
+
For modals, toasts, sheets, side drawers — reach for the **imperative service API** first:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { $dialog, $notify, schmancyContentDrawer, sheet, SchmancySheetPosition } from '@mhmo91/schmancy'
|
|
36
|
+
|
|
37
|
+
$dialog.component(new EditForm()) // modal
|
|
38
|
+
$dialog.component(new QuickPicker(), { position: e }) // anchored modal
|
|
39
|
+
$notify.success('Saved'); $notify.error('Failed') // toast
|
|
40
|
+
schmancyContentDrawer.open({ component: new Detail() }) // side panel
|
|
41
|
+
sheet.open({ component: new Picker(), position: SchmancySheetPosition.BOTTOM }) // bottom sheet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
References: `dialog.md`, `notification.md`, `content-drawer.md`, `sheet.md`.
|
|
45
|
+
|
|
46
|
+
Use component tags (`<schmancy-menu>`, `<schmancy-dropdown>`, `<schmancy-tooltip>`, `<schmancy-lightbox>`, `<schmancy-expand>`) only when the tag is the natural fit (anchored panels, tooltips, galleries).
|
|
47
|
+
|
|
48
|
+
## Non-negotiable conventions
|
|
49
|
+
|
|
50
|
+
**Component authoring**
|
|
51
|
+
- Every component extends `$LitElement(style?)`. Never raw `LitElement`.
|
|
52
|
+
- Every RxJS subscription ends with `.pipe(takeUntil(this.disconnecting))`.
|
|
53
|
+
- Register the tag in `HTMLElementTagNameMap` for TypeScript.
|
|
54
|
+
|
|
55
|
+
**State**
|
|
56
|
+
- Contexts live at module scope. Many small contexts beat one monolith.
|
|
57
|
+
- Gate subscriptions with `filter(() => ctx.ready)` when reading persisted contexts.
|
|
58
|
+
- Storage tiers: `'memory'` (regenerable) · `'session'` (per-tab) · `'local'` (user prefs) · `'indexeddb'` (>100-entry collections).
|
|
59
|
+
|
|
60
|
+
**Routing**
|
|
61
|
+
- Route guards are `Observable<boolean>`, never cached booleans.
|
|
62
|
+
- `when="tag-name"` must exactly match `@customElement('tag-name')`.
|
|
63
|
+
- Lazy-load route components: `lazy(() => import('./page'))`.
|
|
64
|
+
- After auth/permission guards, use `historyStrategy: 'replace'` or `'pop'` — never `'push'`.
|
|
65
|
+
|
|
66
|
+
**Templates**
|
|
67
|
+
- Lists: `repeat(items, i => i.id, tpl)`. Never `.map()`.
|
|
68
|
+
- View switching: `cache(...)`.
|
|
69
|
+
- Expensive work: `guard([deps], () => expensive())`.
|
|
70
|
+
- Conditionals: `when(...)` / `choose(...)` / `ifDefined(...)`.
|
|
71
|
+
- DOM access: `ref(createRef())`.
|
|
72
|
+
- `classMap(this.classMap({...}))` must be the sole expression in `class=` — never mix with string interpolation.
|
|
73
|
+
|
|
74
|
+
**Styling**
|
|
75
|
+
- Colors: `--schmancy-sys-color-*` CSS vars or Tailwind theme classes. Never hardcoded hex.
|
|
76
|
+
- No `setTimeout` / `setInterval` / `addEventListener` — use RxJS (`timer`, `interval`, `fromEvent`).
|
|
77
|
+
|
|
78
|
+
**Accessibility (combobox forms)**
|
|
79
|
+
```typescript
|
|
80
|
+
role="combobox"
|
|
81
|
+
aria-haspopup="listbox"
|
|
82
|
+
aria-expanded=${this._open}
|
|
83
|
+
aria-controls="listbox-id"
|
|
84
|
+
```
|
|
85
|
+
Plus a live region: `<div id="live-status" role="status" aria-live="polite" class="sr-only"></div>`.
|
|
86
|
+
|
|
87
|
+
## Minimal app skeleton
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
<schmancy-theme root scheme="dark">
|
|
91
|
+
<schmancy-surface type="solid" fill="all">
|
|
92
|
+
<schmancy-scroll>
|
|
93
|
+
<schmancy-area
|
|
94
|
+
name="root"
|
|
95
|
+
.default=${lazy(() => import('./home.page'))}
|
|
96
|
+
>
|
|
97
|
+
<schmancy-route when="home-page"
|
|
98
|
+
.component=${lazy(() => import('./home.page'))}></schmancy-route>
|
|
99
|
+
|
|
100
|
+
<schmancy-route when="app-index"
|
|
101
|
+
.component=${lazy(() => import('./app.page'))}
|
|
102
|
+
.guard=${authState$.pipe(
|
|
103
|
+
map(u => !!u),
|
|
104
|
+
takeUntil(this.disconnecting),
|
|
105
|
+
)}
|
|
106
|
+
@redirect=${() => area.push({
|
|
107
|
+
component: 'home-page', area: 'root', historyStrategy: 'replace',
|
|
108
|
+
})}></schmancy-route>
|
|
109
|
+
</schmancy-area>
|
|
110
|
+
</schmancy-scroll>
|
|
111
|
+
</schmancy-surface>
|
|
112
|
+
</schmancy-theme>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Workflow
|
|
116
|
+
|
|
117
|
+
1. User describes a UI task.
|
|
118
|
+
2. Read `INDEX.md` to find the relevant components or foundations.
|
|
119
|
+
3. Read the specific `.md` files for the APIs involved.
|
|
120
|
+
4. Write code that follows the conventions above.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mhmo91/schmancy",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "UI library build with web components",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"customElements": "custom-elements.json",
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
"types": "./types/mixins/index.d.ts",
|
|
14
14
|
"default": "./mixins/index.ts"
|
|
15
15
|
},
|
|
16
|
-
"./ai/*": "./ai/*",
|
|
17
16
|
"./*": {
|
|
18
17
|
"types": "./types/src/*/index.d.ts",
|
|
19
18
|
"default": "./dist/*.js"
|
|
@@ -37,7 +36,8 @@
|
|
|
37
36
|
"types",
|
|
38
37
|
"src",
|
|
39
38
|
"mixins",
|
|
40
|
-
"
|
|
39
|
+
".claude-plugin",
|
|
40
|
+
"skills",
|
|
41
41
|
"custom-elements.json",
|
|
42
42
|
"README.md"
|
|
43
43
|
],
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Schmancy — Documentation Index
|
|
2
|
+
|
|
3
|
+
A Web Component UI library on Lit + RxJS + Tailwind CSS.
|
|
4
|
+
|
|
5
|
+
## Foundations
|
|
6
|
+
|
|
7
|
+
The framework pieces — touch before components.
|
|
8
|
+
|
|
9
|
+
- [Area](./area.md) — `<schmancy-area>`, `<schmancy-route>`, `area.push()`, `lazy()` for routing.
|
|
10
|
+
- [Store](./store.md) — `createContext`, `@select`, `@selectItem`, storage backends.
|
|
11
|
+
- [Mixins](./mixins.md) — `$LitElement` base class.
|
|
12
|
+
- [Theme](./theme.md) — `<schmancy-theme>`, color scheme, CSS variables.
|
|
13
|
+
- [Directives](./directives.md) — Lit directives for physics, effects, text, visibility, interaction.
|
|
14
|
+
- [Animation](./animation.md) — Spring presets (`SPRING_SMOOTH`, etc.), `createAnimation`.
|
|
15
|
+
|
|
16
|
+
## Components by job
|
|
17
|
+
|
|
18
|
+
### Display
|
|
19
|
+
[Typography](./typography.md) · [Icons](./icons.md) · [Avatar](./avatar.md) · [Divider](./divider.md) · [Badge](./badge.md) · [Code Highlight](./code-highlight.md) · [Typewriter](./typewriter.md) · [JSON](./json.md) · [Iframe](./iframe.md) · [Map](./map.md) · [Charts](./charts.md)
|
|
20
|
+
|
|
21
|
+
### Surfaces & layout
|
|
22
|
+
[Surface](./surface.md) · [Card](./card.md) · [Scroll / Grid / Flex](./layout.md) · [Page](./page.md) · [Content Drawer](./content-drawer.md) · [Window](./window.md) · [Boat](./boat.md) · [Float](./float.md)
|
|
23
|
+
|
|
24
|
+
### Forms
|
|
25
|
+
[Form](./form.md) · [Input](./input.md) · [Textarea](./textarea.md) · [Select](./select.md) · [Autocomplete](./autocomplete.md) · [Option](./option.md) · [Checkbox](./checkbox.md) · [Radio Group](./radio-group.md) · [Chips](./chips.md) · [Date Range](./date-range.md) · [Date Range Inline](./date-range-inline.md) · [Range](./range.md) · [Extra (Country/Timezone)](./extra.md)
|
|
26
|
+
|
|
27
|
+
### Navigation
|
|
28
|
+
[Nav Drawer](./nav-drawer.md) · [Tabs](./tabs.md) · [Navigation Bar](./navigation-bar.md) · [Navigation Rail](./navigation-rail.md) · [Steps](./steps.md) · [Teleport](./teleport.md) · [Theme Button](./theme-button.md)
|
|
29
|
+
|
|
30
|
+
### Overlays
|
|
31
|
+
[Dialog](./dialog.md) · [Sheet](./sheet.md) · [Notification](./notification.md) · [Menu](./menu.md) · [Dropdown](./dropdown.md) · [Tooltip](./tooltip.md) · [Lightbox](./lightbox.md) · [Expand](./expand.md)
|
|
32
|
+
|
|
33
|
+
### Interactive
|
|
34
|
+
[Button](./button.md) · [List](./list.md) · [Details](./details.md) · [Table](./table.md) · [Tree](./tree.md) · [Slider](./slider.md) · [QR Scanner](./qr-scanner.md)
|
|
35
|
+
|
|
36
|
+
### Feedback
|
|
37
|
+
[Progress](./progress.md) · [Busy](./busy.md) · [Connectivity](./connectivity.md) · [Delay](./delay.md)
|
|
38
|
+
|
|
39
|
+
### Domain
|
|
40
|
+
[Mailbox](./mailbox.md)
|
|
41
|
+
|
|
42
|
+
## Services (imperative APIs)
|
|
43
|
+
|
|
44
|
+
| Service | Purpose |
|
|
45
|
+
|---------|---------|
|
|
46
|
+
| `area` | Route navigation (see [area](./area.md)) |
|
|
47
|
+
| `$dialog` | Open dialogs (see [dialog](./dialog.md)) |
|
|
48
|
+
| `$notify` | Toast notifications (see [notification](./notification.md)) |
|
|
49
|
+
| `schmancyContentDrawer` | Side panel (see [content-drawer](./content-drawer.md)) |
|
|
50
|
+
| `theme` | Theme state, `fullscreen$` (see [theme](./theme.md)) |
|
|
51
|
+
| `sound` | Audio feedback (see [audio](./audio.md)) |
|
|
52
|
+
| `overlayStack` | Z-index coordinator (see [utils](./utils.md)) |
|
|
53
|
+
| `windowManager` | Window registry (see [window](./window.md)) |
|
|
54
|
+
|
|
55
|
+
## Utilities
|
|
56
|
+
|
|
57
|
+
[Discovery](./discovery.md) — cross-shadow component lookup.
|
|
58
|
+
[RxJS Utils](./rxjs-utils.md) — `waitForElement`, `waitUntil`, `mutationObserver`.
|
|
59
|
+
[Utils](./utils.md) — `similarity`, `numbers`, `overlayStack`, `intersection$`, `hashContent`.
|
|
60
|
+
[Audio](./audio.md) — synthesized feedback sounds.
|
|
61
|
+
|
|
62
|
+
## Conventions
|
|
63
|
+
|
|
64
|
+
- Lists use `repeat(items, item => item.id, tpl)`.
|
|
65
|
+
- View switching uses `cache(...)`.
|
|
66
|
+
- Expensive work uses `guard([deps], fn)`.
|
|
67
|
+
- DOM access uses `ref(createRef())`.
|
|
68
|
+
- Conditionals use `when(...)`, `choose(...)`, `ifDefined(...)`.
|
|
69
|
+
- All RxJS subscriptions end with `.pipe(takeUntil(this.disconnecting))`.
|
|
70
|
+
- Don't use `setTimeout` / `setInterval` / `addEventListener` — use RxJS (`timer`, `interval`, `fromEvent`).
|
|
71
|
+
- Colors come from `--schmancy-sys-color-*` CSS vars or Tailwind theme classes.
|
|
72
|
+
- `classMap(...)` must be the sole expression in `class=`; never mix with string interpolation.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: schmancy
|
|
3
|
+
description: UI patterns, component APIs, and conventions for the @mhmo91/schmancy web-component library (Lit + RxJS + Tailwind). Activate whenever the user works on any <schmancy-*> tag, routing with schmancy-area, state with createContext/@select, the $LitElement base class, theme, directives, or overlay services ($dialog, $notify, schmancyContentDrawer, sheet).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Schmancy
|
|
7
|
+
|
|
8
|
+
Web-component UI library on Lit + RxJS + Tailwind CSS. This skill bundles the full library reference as supporting files alongside this SKILL.md.
|
|
9
|
+
|
|
10
|
+
## How to use this skill
|
|
11
|
+
|
|
12
|
+
All reference files live in this directory. Read by filename.
|
|
13
|
+
|
|
14
|
+
1. **Start with `INDEX.md`** for the full catalog organized by job (foundations / atoms / forms / navigation / overlays / interaction / feedback / display).
|
|
15
|
+
2. **Before writing any `<schmancy-X>` tag**, read `X.md`. Example: `<schmancy-button>` → `button.md`.
|
|
16
|
+
3. **Before editing foundations** (routing, state, base class, theme), read the matching foundation file below.
|
|
17
|
+
4. **Apply the conventions** at the end of this file.
|
|
18
|
+
|
|
19
|
+
## Foundations (the framework pieces — touch first)
|
|
20
|
+
|
|
21
|
+
| Piece | Read |
|
|
22
|
+
|-------|------|
|
|
23
|
+
| Routing (`<schmancy-area>`, `<schmancy-route>`, `area.push()`, `lazy()`) | `area.md` |
|
|
24
|
+
| State (`createContext`, `@select`, `@selectItem`) | `store.md` |
|
|
25
|
+
| Base class (`$LitElement`) | `mixins.md` |
|
|
26
|
+
| Theme (`<schmancy-theme>`, `theme` service) | `theme.md` |
|
|
27
|
+
| Directives (`magnetic`, `cursorGlow`, `gravity`, `reveal`, `animateText`, …) | `directives.md` |
|
|
28
|
+
| Spring physics presets | `animation.md` |
|
|
29
|
+
|
|
30
|
+
## Overlay services (prefer over tags)
|
|
31
|
+
|
|
32
|
+
For modals, toasts, sheets, side drawers — reach for the **imperative service API** first:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { $dialog, $notify, schmancyContentDrawer, sheet, SchmancySheetPosition } from '@mhmo91/schmancy'
|
|
36
|
+
|
|
37
|
+
$dialog.component(new EditForm()) // modal
|
|
38
|
+
$dialog.component(new QuickPicker(), { position: e }) // anchored modal
|
|
39
|
+
$notify.success('Saved'); $notify.error('Failed') // toast
|
|
40
|
+
schmancyContentDrawer.open({ component: new Detail() }) // side panel
|
|
41
|
+
sheet.open({ component: new Picker(), position: SchmancySheetPosition.BOTTOM }) // bottom sheet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
References: `dialog.md`, `notification.md`, `content-drawer.md`, `sheet.md`.
|
|
45
|
+
|
|
46
|
+
Use component tags (`<schmancy-menu>`, `<schmancy-dropdown>`, `<schmancy-tooltip>`, `<schmancy-lightbox>`, `<schmancy-expand>`) only when the tag is the natural fit (anchored panels, tooltips, galleries).
|
|
47
|
+
|
|
48
|
+
## Non-negotiable conventions
|
|
49
|
+
|
|
50
|
+
**Component authoring**
|
|
51
|
+
- Every component extends `$LitElement(style?)`. Never raw `LitElement`.
|
|
52
|
+
- Every RxJS subscription ends with `.pipe(takeUntil(this.disconnecting))`.
|
|
53
|
+
- Register the tag in `HTMLElementTagNameMap` for TypeScript.
|
|
54
|
+
|
|
55
|
+
**State**
|
|
56
|
+
- Contexts live at module scope. Many small contexts beat one monolith.
|
|
57
|
+
- Gate subscriptions with `filter(() => ctx.ready)` when reading persisted contexts.
|
|
58
|
+
- Storage tiers: `'memory'` (regenerable) · `'session'` (per-tab) · `'local'` (user prefs) · `'indexeddb'` (>100-entry collections).
|
|
59
|
+
|
|
60
|
+
**Routing**
|
|
61
|
+
- Route guards are `Observable<boolean>`, never cached booleans.
|
|
62
|
+
- `when="tag-name"` must exactly match `@customElement('tag-name')`.
|
|
63
|
+
- Lazy-load route components: `lazy(() => import('./page'))`.
|
|
64
|
+
- After auth/permission guards, use `historyStrategy: 'replace'` or `'pop'` — never `'push'`.
|
|
65
|
+
|
|
66
|
+
**Templates**
|
|
67
|
+
- Lists: `repeat(items, i => i.id, tpl)`. Never `.map()`.
|
|
68
|
+
- View switching: `cache(...)`.
|
|
69
|
+
- Expensive work: `guard([deps], () => expensive())`.
|
|
70
|
+
- Conditionals: `when(...)` / `choose(...)` / `ifDefined(...)`.
|
|
71
|
+
- DOM access: `ref(createRef())`.
|
|
72
|
+
- `classMap(this.classMap({...}))` must be the sole expression in `class=` — never mix with string interpolation.
|
|
73
|
+
|
|
74
|
+
**Styling**
|
|
75
|
+
- Colors: `--schmancy-sys-color-*` CSS vars or Tailwind theme classes. Never hardcoded hex.
|
|
76
|
+
- No `setTimeout` / `setInterval` / `addEventListener` — use RxJS (`timer`, `interval`, `fromEvent`).
|
|
77
|
+
|
|
78
|
+
**Accessibility (combobox forms)**
|
|
79
|
+
```typescript
|
|
80
|
+
role="combobox"
|
|
81
|
+
aria-haspopup="listbox"
|
|
82
|
+
aria-expanded=${this._open}
|
|
83
|
+
aria-controls="listbox-id"
|
|
84
|
+
```
|
|
85
|
+
Plus a live region: `<div id="live-status" role="status" aria-live="polite" class="sr-only"></div>`.
|
|
86
|
+
|
|
87
|
+
## Minimal app skeleton
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
<schmancy-theme root scheme="dark">
|
|
91
|
+
<schmancy-surface type="solid" fill="all">
|
|
92
|
+
<schmancy-scroll>
|
|
93
|
+
<schmancy-area
|
|
94
|
+
name="root"
|
|
95
|
+
.default=${lazy(() => import('./home.page'))}
|
|
96
|
+
>
|
|
97
|
+
<schmancy-route when="home-page"
|
|
98
|
+
.component=${lazy(() => import('./home.page'))}></schmancy-route>
|
|
99
|
+
|
|
100
|
+
<schmancy-route when="app-index"
|
|
101
|
+
.component=${lazy(() => import('./app.page'))}
|
|
102
|
+
.guard=${authState$.pipe(
|
|
103
|
+
map(u => !!u),
|
|
104
|
+
takeUntil(this.disconnecting),
|
|
105
|
+
)}
|
|
106
|
+
@redirect=${() => area.push({
|
|
107
|
+
component: 'home-page', area: 'root', historyStrategy: 'replace',
|
|
108
|
+
})}></schmancy-route>
|
|
109
|
+
</schmancy-area>
|
|
110
|
+
</schmancy-scroll>
|
|
111
|
+
</schmancy-surface>
|
|
112
|
+
</schmancy-theme>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Workflow
|
|
116
|
+
|
|
117
|
+
1. User describes a UI task.
|
|
118
|
+
2. Read `INDEX.md` to find the relevant components or foundations.
|
|
119
|
+
3. Read the specific `.md` files for the APIs involved.
|
|
120
|
+
4. Write code that follows the conventions above.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Blackbird Animation System
|
|
2
|
+
|
|
3
|
+
> Spring physics animation presets for the Web Animations API and CSS transitions.
|
|
4
|
+
|
|
5
|
+
## Spring Presets
|
|
6
|
+
|
|
7
|
+
| Preset | Duration | Character | Best For |
|
|
8
|
+
|--------|----------|-----------|----------|
|
|
9
|
+
| `SPRING_SMOOTH` | 500ms | Apple-style, subtle overshoot | Accordions, content reveals |
|
|
10
|
+
| `SPRING_SNAPPY` | 300ms | Quick, minimal overshoot | Buttons, toggles |
|
|
11
|
+
| `SPRING_BOUNCY` | 600ms | Playful, noticeable overshoot | Notifications, celebrations |
|
|
12
|
+
| `SPRING_GENTLE` | 700ms | Slow, no overshoot | Page transitions, modals |
|
|
13
|
+
|
|
14
|
+
## Usage with Web Animations API
|
|
15
|
+
```typescript
|
|
16
|
+
import { createAnimation, SPRING_SMOOTH } from '@mhmo91/schmancy'
|
|
17
|
+
|
|
18
|
+
const anim = createAnimation(SPRING_SMOOTH, {
|
|
19
|
+
from: { opacity: 0, transform: 'translateY(-16px)' },
|
|
20
|
+
to: { opacity: 1, transform: 'translateY(0)' }
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
element.animate(anim.keyframes, anim.options)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Helper Functions
|
|
27
|
+
```typescript
|
|
28
|
+
import {
|
|
29
|
+
createRevealAnimation, // Fade in + slide up
|
|
30
|
+
createDismissAnimation, // Fade out + slide up
|
|
31
|
+
createScaleAnimation, // Pop in/out
|
|
32
|
+
getEasing, // Auto-detect linear() support
|
|
33
|
+
prefersReducedMotion // Check reduced motion preference
|
|
34
|
+
} from '@mhmo91/schmancy'
|
|
35
|
+
|
|
36
|
+
// Reveal animation
|
|
37
|
+
const reveal = createRevealAnimation(SPRING_SMOOTH, 16) // 16px distance
|
|
38
|
+
element.animate(reveal.keyframes, reveal.options)
|
|
39
|
+
|
|
40
|
+
// Scale animation
|
|
41
|
+
const scale = createScaleAnimation(SPRING_SNAPPY, 0.9, 1)
|
|
42
|
+
element.animate(scale.keyframes, scale.options)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## CSS Custom Properties
|
|
46
|
+
```css
|
|
47
|
+
/* Available after injecting ANIMATION_CSS_VARS */
|
|
48
|
+
.element {
|
|
49
|
+
transition: transform var(--blackbird-duration-smooth) var(--blackbird-easing-smooth);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Tailwind Integration
|
|
54
|
+
```typescript
|
|
55
|
+
import { tailwindAnimations } from '@mhmo91/schmancy'
|
|
56
|
+
// Use in tailwind.config.js extend block
|
|
57
|
+
|
|
58
|
+
// Available classes:
|
|
59
|
+
// ease-spring-smooth, ease-spring-snappy, ease-spring-bouncy, ease-spring-gentle
|
|
60
|
+
// duration-spring-smooth, duration-spring-snappy, etc.
|
|
61
|
+
// animate-blackbird-reveal, animate-blackbird-dismiss, etc.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
All animations respect `prefers-reduced-motion: reduce` (instant transitions, no animation).
|