@ikas/component-cli 0.83.0 → 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +34 -793
- package/dist/commands/create.js.map +1 -1
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +9 -65
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/observer-runtime.d.ts.map +1 -1
- package/dist/utils/observer-runtime.js +2 -37
- package/dist/utils/observer-runtime.js.map +1 -1
- package/dist/utils/template.d.ts +8 -0
- package/dist/utils/template.d.ts.map +1 -0
- package/dist/utils/template.js +24 -0
- package/dist/utils/template.js.map +1 -0
- package/package.json +3 -2
- package/templates/add/component.css +13 -0
- package/templates/add/component.tsx +12 -0
- package/templates/add/section.css +17 -0
- package/templates/add/section.tsx +14 -0
- package/templates/create/CLAUDE.md +258 -0
- package/templates/create/README.md +50 -0
- package/templates/create/cursorrules +108 -0
- package/templates/create/gitignore +5 -0
- package/templates/create/ikas.config.json +95 -0
- package/templates/create/mcp.json +10 -0
- package/templates/create/package.json +21 -0
- package/templates/create/src/components/ExampleComponent/index.tsx +22 -0
- package/templates/create/src/components/ExampleComponent/styles.css +36 -0
- package/templates/create/src/components/ExampleComponent/types.ts +7 -0
- package/templates/create/src/components/ExampleSection/index.tsx +14 -0
- package/templates/create/src/components/ExampleSection/styles.css +29 -0
- package/templates/create/src/components/ExampleSection/types.ts +6 -0
- package/templates/create/src/components/index.ts +2 -0
- package/templates/create/src/global-types.ts +5 -0
- package/templates/create/src/global.css +12 -0
- package/templates/create/src/ikas-component-utils.d.ts +3 -0
- package/templates/create/tsconfig.json +30 -0
- package/templates/create/vite.config.ts +15 -0
- package/templates/observer-runtime.js +34 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
An ikas code components project.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Install dependencies:
|
|
8
|
+
```bash
|
|
9
|
+
npm install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Start the development server:
|
|
13
|
+
```bash
|
|
14
|
+
npm run dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
3. Open the ikas editor and connect to the dev server from the Dev Components panel.
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
- `npm run dev` - Start development server with live editor updates
|
|
22
|
+
- `npm run build` - Build components for production
|
|
23
|
+
- `npm run add` - Add a new component to the project
|
|
24
|
+
|
|
25
|
+
## Project Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
{{PROJECT_NAME}}/
|
|
29
|
+
├── src/
|
|
30
|
+
│ ├── components/
|
|
31
|
+
│ │ ├── ExampleComponent/ # A child component (type: "component")
|
|
32
|
+
│ │ │ ├── index.tsx
|
|
33
|
+
│ │ │ ├── styles.css
|
|
34
|
+
│ │ │ └── types.ts
|
|
35
|
+
│ │ ├── ExampleSection/ # A page-level section (type: "section")
|
|
36
|
+
│ │ │ ├── index.tsx
|
|
37
|
+
│ │ │ ├── styles.css
|
|
38
|
+
│ │ │ └── types.ts
|
|
39
|
+
│ │ └── index.ts
|
|
40
|
+
│ ├── global.css # Unscoped global styles
|
|
41
|
+
│ └── global-types.ts # Auto-generated shared enum types
|
|
42
|
+
├── ikas.config.json
|
|
43
|
+
├── package.json
|
|
44
|
+
├── tsconfig.json
|
|
45
|
+
└── vite.config.ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Building for Production
|
|
49
|
+
|
|
50
|
+
Run `npm run build` to compile your components. The output will be ready to upload to the ikas editor.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# ikas Code Components
|
|
2
|
+
|
|
3
|
+
You are building **Preact + TypeScript components for an e-commerce storefront**.
|
|
4
|
+
**ALWAYS query MCP tools before writing code that uses storefront APIs.**
|
|
5
|
+
|
|
6
|
+
## CRITICAL: Auto-Generated Files
|
|
7
|
+
|
|
8
|
+
**NEVER manually create or edit `types.ts` or `global-types.ts`** — they are auto-generated by CLI commands.
|
|
9
|
+
Use `npx ikas-component config add-component --props '[...]'` or `npx ikas-component config add-prop` to manage props.
|
|
10
|
+
These commands update `ikas.config.json`, `types.ts`, and `global-types.ts` automatically.
|
|
11
|
+
|
|
12
|
+
## MCP Tools (12 tools)
|
|
13
|
+
|
|
14
|
+
### Starting a New Section
|
|
15
|
+
- get_section_template(sectionType) — **Start here** — production-ready starter template for common sections (header, footer, product-detail, product-list, cart, login, hero-banner, blog-post, faq, etc.)
|
|
16
|
+
- get_framework_guide(topic) — Framework docs ("ai-workflow", "common-pitfalls", "prop-types", "css-scoping", "form-handling", "imports")
|
|
17
|
+
- get_code_example(task) — Code examples ("add to cart", "variant selection", "image-handling")
|
|
18
|
+
|
|
19
|
+
### Looking Up APIs
|
|
20
|
+
- search_docs(query) — Search all storefront API docs and framework guides
|
|
21
|
+
- get_function_doc(name) — Full docs for a function (e.g. "addItemToCart", "Router.navigate")
|
|
22
|
+
- list_functions(category?) — List functions by category (ProductDetail, Cart, ProductList, Navigation, Customer, Order, Image, Blog, Brand, Pricing, Form, Validation, Pagination, Filtering)
|
|
23
|
+
- get_prop_types() — All available ikas.config.json prop types
|
|
24
|
+
|
|
25
|
+
### Exploring Types
|
|
26
|
+
- get_model_guide(model) — **One-stop-shop** — type def + utility functions + examples for a model (e.g. "IkasProduct", "IkasOrder")
|
|
27
|
+
- get_type_definition(name) — Full definition of a type or enum
|
|
28
|
+
- get_functions_for_type(typeName) — All utility functions for a type
|
|
29
|
+
- search_types(query) — Search types/enums by keyword ("price", "address", "status")
|
|
30
|
+
- list_types(domain?, kind?) — List all types, filter by domain or kind ("type"/"enum")
|
|
31
|
+
|
|
32
|
+
## CLI Commands (never edit ikas.config.json or types.ts manually)
|
|
33
|
+
- npx ikas-component config add-component --name "Name" --type section --props '[...]' — **Primary** — create with all props in one command
|
|
34
|
+
- npx ikas-component config add-component --name "Name" --type section — Create component with no props
|
|
35
|
+
- npx ikas-component config add-prop --component "Name" --name title --displayName "Title" --type TEXT --required [--group content] — Add a prop incrementally
|
|
36
|
+
- npx ikas-component config update-prop --component "Name" --prop title --type RICH_TEXT [--group colors] — Update a prop or group
|
|
37
|
+
- npx ikas-component config remove-prop --component "Name" --prop title — Remove a prop
|
|
38
|
+
- npx ikas-component config remove-component --name "Name" — Remove a component
|
|
39
|
+
- npx ikas-component config add-prop-group --component "Name" --id colors --name "Colors" [--parent style] — Create a prop group
|
|
40
|
+
- npx ikas-component config update-prop-group --component "Name" --id colors [--name "..."] — Update a prop group
|
|
41
|
+
- npx ikas-component config remove-prop-group --component "Name" --id colors — Remove a prop group
|
|
42
|
+
- npx ikas-component config list — List all components and their props
|
|
43
|
+
- npx ikas-component check --json — Type-check all components
|
|
44
|
+
- npx ikas-component build — Compile server.js + client.js + styles.css per component
|
|
45
|
+
- npx ikas-component dev — Start dev server (Vite 5200 + WebSocket 5201)
|
|
46
|
+
|
|
47
|
+
## Workflow: Building a New Section
|
|
48
|
+
1. get_section_template("product-detail") → get starter files + CLI command with --props
|
|
49
|
+
2. Run the CLI command (creates component + props + types.ts in one step)
|
|
50
|
+
3. Write index.tsx and styles.css using the template (do NOT edit types.ts — it's already generated)
|
|
51
|
+
4. Look up APIs: get_model_guide("IkasProduct"), get_function_doc("addItemToCart")
|
|
52
|
+
5. npx ikas-component check --json → fix type errors
|
|
53
|
+
6. npx ikas-component build → verify clean build
|
|
54
|
+
|
|
55
|
+
## Sub-Component Structure
|
|
56
|
+
**ALWAYS create sub-components in `src/sub-components/` with their own folder containing `index.tsx` and `styles.css`.**
|
|
57
|
+
- `src/components/` = registered in ikas.config.json. `src/sub-components/` = internal helpers (NOT in ikas.config.json)
|
|
58
|
+
- Sub-components do NOT have `types.ts` — define `Props` inline in `index.tsx`
|
|
59
|
+
- Custom enum types are exported from `src/global-types.ts` (auto-generated). Sub-components can import them: `import type { MyEnum } from "../../global-types";`
|
|
60
|
+
- CSS: `@import "../../sub-components/ProductCard/styles.css";` in parent styles.css
|
|
61
|
+
- TSX: `import ProductCard from "../../sub-components/ProductCard";`
|
|
62
|
+
- Sub-components that read MobX stores need `observer()`, others don't
|
|
63
|
+
- Sub-components can be shared across multiple parent sections
|
|
64
|
+
- NEVER create flat .tsx files inside a component folder
|
|
65
|
+
|
|
66
|
+
## Key Patterns
|
|
67
|
+
- Root components are automatically reactive (ikas runtime uses autorun). Do NOT use observer() on root exports.
|
|
68
|
+
Pattern: `export function MySection({ title }: Props) { ... }` + `export default MySection;`
|
|
69
|
+
Only use observer() on extracted sub-components that independently read MobX stores.
|
|
70
|
+
- Null safety: storefront models can be null — always check before accessing
|
|
71
|
+
- Mutations: addItemToCart() etc. mutate MobX observables in-place — no return capture needed
|
|
72
|
+
- COMPONENT & COMPONENT_LIST props: slot-based child components rendered via `<IkasComponentRenderer>`
|
|
73
|
+
`import { IkasComponentRenderer } from "@ikas/bp-storefront"`
|
|
74
|
+
`<IkasComponentRenderer components={myList as any[]} parentProps={props} />`
|
|
75
|
+
Always pass `parentProps={props}` so children can access parent data. Cast with `as any[]`.
|
|
76
|
+
- CSS: write plain class names — auto-scoped with .cc_{componentId} at build time
|
|
77
|
+
- Events: use onInput (not onChange) for text inputs (Preact behavior)
|
|
78
|
+
- Imports: `import { addItemToCart, IkasProduct } from "@ikas/bp-storefront"`
|
|
79
|
+
|
|
80
|
+
## No Static Text Rule
|
|
81
|
+
**CRITICAL: Never hardcode user-visible text in JSX.** All text strings (headings, button labels,
|
|
82
|
+
empty states, loading messages, form labels) MUST be TEXT props with defaultValues.
|
|
83
|
+
Wrong: `<h1>Sign In</h1>`
|
|
84
|
+
Correct: `<h1>{title}</h1>` with `title` as TEXT prop (defaultValue: "Sign In")
|
|
85
|
+
For button loading states, use two separate props (e.g., `submitButtonText` + `submittingButtonText`).
|
|
86
|
+
Group text props under a "Texts" propGroup when the component has 5+ props.
|
|
87
|
+
|
|
88
|
+
## Sections vs Components
|
|
89
|
+
- Sections = page-level containers (Header, Hero, Product Grid, Footer)
|
|
90
|
+
Set "type": "section" via CLI. Use <section> root element. Props interface: Props.
|
|
91
|
+
**Sections MUST always include a `backgroundColor` COLOR prop** (default: `#ffffff`).
|
|
92
|
+
Apply via inline style: `style={backgroundColor ? { backgroundColor } : undefined}`
|
|
93
|
+
Consider also adding `textColor` COLOR props for text elements directly on the section background.
|
|
94
|
+
- Components = child elements inside sections (buttons, cards, badges)
|
|
95
|
+
Defaults to "component". Use <div> root element. Props interface: Props.
|
|
96
|
+
|
|
97
|
+
## Prop Groups
|
|
98
|
+
Organize 5+ props into collapsible groups in editor sidebar.
|
|
99
|
+
- Define groups in `propGroups` on component in ikas.config.json
|
|
100
|
+
- Assign props via `groupId` on each prop
|
|
101
|
+
- Nest 1 level deep with `children`
|
|
102
|
+
- Group IDs must be unique within a component
|
|
103
|
+
- CLI: add-prop-group, update-prop-group, remove-prop-group
|
|
104
|
+
- Add prop to group: add-prop --group <groupId> or update-prop --group <groupId>
|
|
105
|
+
|
|
106
|
+
## Build Verification
|
|
107
|
+
IMPORTANT: After completing any task, always run `npx ikas-component build` (or `npm run build`)
|
|
108
|
+
to check for TypeScript and build errors. Fix any errors before considering the task done.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"projectId": "{{PROJECT_ID}}",
|
|
5
|
+
"globalStyles": "./src/global.css",
|
|
6
|
+
"components": [
|
|
7
|
+
{
|
|
8
|
+
"id": "{{EXAMPLE_COMPONENT_ID}}",
|
|
9
|
+
"name": "Example Component",
|
|
10
|
+
"entry": "./src/components/ExampleComponent/index.tsx",
|
|
11
|
+
"styles": "./src/components/ExampleComponent/styles.css",
|
|
12
|
+
"props": [
|
|
13
|
+
{
|
|
14
|
+
"name": "title",
|
|
15
|
+
"displayName": "Title",
|
|
16
|
+
"type": "TEXT",
|
|
17
|
+
"required": true,
|
|
18
|
+
"defaultValue": "Hello World",
|
|
19
|
+
"description": "The main title text"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "description",
|
|
23
|
+
"displayName": "Description",
|
|
24
|
+
"type": "TEXT",
|
|
25
|
+
"required": false,
|
|
26
|
+
"defaultValue": "This is an example ikas code component built with Preact.",
|
|
27
|
+
"description": "The description text below the title"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "showButton",
|
|
31
|
+
"displayName": "Show Button",
|
|
32
|
+
"type": "BOOLEAN",
|
|
33
|
+
"required": false,
|
|
34
|
+
"defaultValue": true,
|
|
35
|
+
"description": "Whether to show the action button"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "buttonText",
|
|
39
|
+
"displayName": "Button Text",
|
|
40
|
+
"type": "TEXT",
|
|
41
|
+
"required": false,
|
|
42
|
+
"defaultValue": "Click Me",
|
|
43
|
+
"description": "The text displayed on the button"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "{{EXAMPLE_SECTION_ID}}",
|
|
49
|
+
"name": "Example Section",
|
|
50
|
+
"entry": "./src/components/ExampleSection/index.tsx",
|
|
51
|
+
"styles": "./src/components/ExampleSection/styles.css",
|
|
52
|
+
"type": "section",
|
|
53
|
+
"props": [
|
|
54
|
+
{
|
|
55
|
+
"name": "heading",
|
|
56
|
+
"displayName": "Heading",
|
|
57
|
+
"type": "TEXT",
|
|
58
|
+
"required": true,
|
|
59
|
+
"defaultValue": "Welcome to Our Store",
|
|
60
|
+
"description": "The section heading text",
|
|
61
|
+
"groupId": "content"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "subtitle",
|
|
65
|
+
"displayName": "Subtitle",
|
|
66
|
+
"type": "TEXT",
|
|
67
|
+
"required": false,
|
|
68
|
+
"defaultValue": "Discover our latest products and collections.",
|
|
69
|
+
"description": "The subtitle text below the heading",
|
|
70
|
+
"groupId": "content"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "backgroundColor",
|
|
74
|
+
"displayName": "Background Color",
|
|
75
|
+
"type": "COLOR",
|
|
76
|
+
"required": false,
|
|
77
|
+
"description": "The section background color",
|
|
78
|
+
"groupId": "appearance"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"propGroups": [
|
|
82
|
+
{
|
|
83
|
+
"id": "content",
|
|
84
|
+
"name": "Content",
|
|
85
|
+
"description": "Text and copy settings"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "appearance",
|
|
89
|
+
"name": "Appearance",
|
|
90
|
+
"description": "Colors and visual style"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "ikas-component dev",
|
|
7
|
+
"build": "ikas-component build",
|
|
8
|
+
"add": "ikas-component add",
|
|
9
|
+
"publish": "ikas-component publish"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"preact": "^10.19.3"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@ikas/component-cli": "*",
|
|
16
|
+
"@ikas/bp-storefront": "*",
|
|
17
|
+
"@ikas/code-components-mcp": "*",
|
|
18
|
+
"typescript": "^5.3.0",
|
|
19
|
+
"vite": "^5.0.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Props } from "./types";
|
|
2
|
+
|
|
3
|
+
export function ExampleComponent({
|
|
4
|
+
title,
|
|
5
|
+
description = "This is an example ikas code component built with Preact.",
|
|
6
|
+
showButton,
|
|
7
|
+
buttonText = "Click Me",
|
|
8
|
+
}: Props) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="example-component">
|
|
11
|
+
<h1 className="example-title">{title}</h1>
|
|
12
|
+
<p className="example-description">{description}</p>
|
|
13
|
+
{showButton && (
|
|
14
|
+
<button className="example-button">
|
|
15
|
+
{buttonText}
|
|
16
|
+
</button>
|
|
17
|
+
)}
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default ExampleComponent;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.example-component {
|
|
2
|
+
padding: 24px;
|
|
3
|
+
border-radius: 8px;
|
|
4
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
5
|
+
color: white;
|
|
6
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.example-title {
|
|
10
|
+
margin: 0 0 12px 0;
|
|
11
|
+
font-size: 28px;
|
|
12
|
+
font-weight: 700;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.example-description {
|
|
16
|
+
margin: 0 0 20px 0;
|
|
17
|
+
font-size: 16px;
|
|
18
|
+
opacity: 0.9;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.example-button {
|
|
22
|
+
padding: 12px 24px;
|
|
23
|
+
border: none;
|
|
24
|
+
border-radius: 6px;
|
|
25
|
+
background: white;
|
|
26
|
+
color: #667eea;
|
|
27
|
+
font-size: 16px;
|
|
28
|
+
font-weight: 600;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.example-button:hover {
|
|
34
|
+
transform: translateY(-2px);
|
|
35
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
36
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Props } from "./types";
|
|
2
|
+
|
|
3
|
+
export function ExampleSection({ heading, subtitle, backgroundColor }: Props) {
|
|
4
|
+
return (
|
|
5
|
+
<section className="example-section" style={backgroundColor ? { backgroundColor } : undefined}>
|
|
6
|
+
<div className="example-section-inner">
|
|
7
|
+
<h2 className="example-section-heading">{heading}</h2>
|
|
8
|
+
{subtitle && <p className="example-section-subtitle">{subtitle}</p>}
|
|
9
|
+
</div>
|
|
10
|
+
</section>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default ExampleSection;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
.example-section {
|
|
2
|
+
width: 100%;
|
|
3
|
+
padding: 64px 24px;
|
|
4
|
+
background: #f8f9fa;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.example-section-inner {
|
|
8
|
+
max-width: 1200px;
|
|
9
|
+
margin: 0 auto;
|
|
10
|
+
text-align: center;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.example-section-heading {
|
|
14
|
+
margin: 0 0 16px 0;
|
|
15
|
+
font-size: 36px;
|
|
16
|
+
font-weight: 700;
|
|
17
|
+
color: #1a1a2e;
|
|
18
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.example-section-subtitle {
|
|
22
|
+
margin: 0;
|
|
23
|
+
font-size: 18px;
|
|
24
|
+
color: #6b7280;
|
|
25
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
26
|
+
max-width: 600px;
|
|
27
|
+
margin-left: auto;
|
|
28
|
+
margin-right: auto;
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Global styles for your ikas code components project.
|
|
3
|
+
* These styles are NOT scoped — they apply across all components.
|
|
4
|
+
* Use this for CSS resets, base typography, utility classes, or CSS variables.
|
|
5
|
+
*
|
|
6
|
+
* Loading order:
|
|
7
|
+
* 1. Global CSS (this file) — lowest specificity
|
|
8
|
+
* 2. Shared chunk CSS — multi-scope (.cc_a .sel, .cc_b .sel)
|
|
9
|
+
* 3. Component CSS — single scope (.cc_id .sel) — highest specificity
|
|
10
|
+
*
|
|
11
|
+
* Component-scoped styles naturally override these globals.
|
|
12
|
+
*/
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"lib": [
|
|
5
|
+
"DOM",
|
|
6
|
+
"DOM.Iterable",
|
|
7
|
+
"ES2022"
|
|
8
|
+
],
|
|
9
|
+
"module": "ESNext",
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"jsx": "react-jsx",
|
|
12
|
+
"jsxImportSource": "preact",
|
|
13
|
+
"strict": true,
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"skipLibCheck": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"resolveJsonModule": true,
|
|
18
|
+
"declaration": true,
|
|
19
|
+
"declarationMap": true,
|
|
20
|
+
"outDir": "./dist",
|
|
21
|
+
"rootDir": "./src"
|
|
22
|
+
},
|
|
23
|
+
"include": [
|
|
24
|
+
"src/**/*"
|
|
25
|
+
],
|
|
26
|
+
"exclude": [
|
|
27
|
+
"node_modules",
|
|
28
|
+
"dist"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import preact from "@preact/preset-vite";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [preact()],
|
|
6
|
+
build: {
|
|
7
|
+
lib: {
|
|
8
|
+
entry: "./src/components/index.ts",
|
|
9
|
+
formats: ["es"]
|
|
10
|
+
},
|
|
11
|
+
rollupOptions: {
|
|
12
|
+
external: ["preact", "preact/hooks", "@ikas/component-utils"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Reaction } from "mobx";
|
|
2
|
+
import { useRef, useState, useEffect } from "preact/hooks";
|
|
3
|
+
|
|
4
|
+
export function observer(Component) {
|
|
5
|
+
var wrapped = function(props) {
|
|
6
|
+
var hookState = useState(0);
|
|
7
|
+
var setTick = hookState[1];
|
|
8
|
+
var reactionRef = useRef(null);
|
|
9
|
+
|
|
10
|
+
if (!reactionRef.current) {
|
|
11
|
+
reactionRef.current = new Reaction(
|
|
12
|
+
"observer(" + (Component.displayName || Component.name || "Component") + ")",
|
|
13
|
+
function() { setTick(function(t) { return t + 1; }); }
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
useEffect(function() {
|
|
18
|
+
return function() {
|
|
19
|
+
if (reactionRef.current) {
|
|
20
|
+
reactionRef.current.dispose();
|
|
21
|
+
reactionRef.current = null;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
var result;
|
|
27
|
+
reactionRef.current.track(function() {
|
|
28
|
+
result = Component(props);
|
|
29
|
+
});
|
|
30
|
+
return result;
|
|
31
|
+
};
|
|
32
|
+
wrapped.displayName = "observer(" + (Component.displayName || Component.name || "Component") + ")";
|
|
33
|
+
return wrapped;
|
|
34
|
+
}
|