remix 3.0.0-beta.0 → 3.0.0-beta.2
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/fetch-router.d.ts +7 -0
- package/dist/fetch-router.d.ts.map +1 -1
- package/dist/node-tsx/load-module.d.ts +2 -0
- package/dist/node-tsx/load-module.d.ts.map +1 -0
- package/dist/node-tsx/load-module.js +2 -0
- package/dist/node-tsx.d.ts +3 -0
- package/dist/node-tsx.d.ts.map +1 -0
- package/{src/node-serve.ts → dist/node-tsx.js} +2 -1
- package/dist/render-middleware.d.ts +2 -0
- package/dist/render-middleware.d.ts.map +1 -0
- package/dist/render-middleware.js +2 -0
- package/dist/route-pattern/href.d.ts +2 -0
- package/dist/route-pattern/href.d.ts.map +1 -0
- package/dist/route-pattern/href.js +2 -0
- package/dist/route-pattern/join.d.ts +2 -0
- package/dist/route-pattern/join.d.ts.map +1 -0
- package/dist/route-pattern/join.js +2 -0
- package/dist/route-pattern/match.d.ts +2 -0
- package/dist/route-pattern/match.d.ts.map +1 -0
- package/dist/route-pattern/match.js +2 -0
- package/package.json +158 -44
- package/src/assert/README.md +109 -0
- package/src/assets/README.md +539 -0
- package/src/async-context-middleware/README.md +100 -0
- package/src/auth/README.md +445 -0
- package/src/auth-middleware/README.md +246 -0
- package/src/cli/README.md +78 -0
- package/src/compression-middleware/README.md +176 -0
- package/src/cookie/README.md +106 -0
- package/src/cop-middleware/README.md +117 -0
- package/src/cors-middleware/README.md +174 -0
- package/src/csrf-middleware/README.md +99 -0
- package/src/data-schema/README.md +422 -0
- package/src/data-table/README.md +552 -0
- package/src/data-table-mysql/README.md +97 -0
- package/src/data-table-postgres/README.md +74 -0
- package/src/data-table-sqlite/README.md +84 -0
- package/src/fetch-proxy/README.md +46 -0
- package/src/fetch-router/README.md +902 -0
- package/src/fetch-router.ts +7 -0
- package/src/file-storage/README.md +57 -0
- package/src/file-storage-s3/README.md +47 -0
- package/src/form-data-middleware/README.md +109 -0
- package/src/form-data-parser/README.md +160 -0
- package/src/fs/README.md +60 -0
- package/src/headers/README.md +629 -0
- package/src/html-template/README.md +101 -0
- package/src/lazy-file/README.md +109 -0
- package/src/logger-middleware/README.md +132 -0
- package/src/method-override-middleware/README.md +71 -0
- package/src/mime/README.md +110 -0
- package/src/multipart-parser/README.md +241 -0
- package/src/node-fetch-server/README.md +352 -0
- package/src/node-tsx/README.md +79 -0
- package/src/node-tsx/load-module.ts +2 -0
- package/{dist/node-serve.js → src/node-tsx.ts} +2 -1
- package/src/render-middleware/README.md +99 -0
- package/src/render-middleware.ts +2 -0
- package/src/route-pattern/README.md +291 -0
- package/src/route-pattern/href.ts +2 -0
- package/src/route-pattern/join.ts +2 -0
- package/src/route-pattern/match.ts +2 -0
- package/src/session/README.md +171 -0
- package/src/session-middleware/README.md +109 -0
- package/src/session-storage-memcache/README.md +37 -0
- package/src/session-storage-redis/README.md +37 -0
- package/src/static-middleware/README.md +89 -0
- package/src/tar-parser/README.md +74 -0
- package/src/terminal/README.md +92 -0
- package/src/test/README.md +430 -0
- package/src/ui/README.md +219 -0
- package/src/ui/accordion/README.md +166 -0
- package/src/ui/anchor/README.md +153 -0
- package/src/ui/animation/README.md +316 -0
- package/src/ui/breadcrumbs/README.md +55 -0
- package/src/ui/button/README.md +44 -0
- package/src/ui/combobox/README.md +145 -0
- package/src/ui/glyph/README.md +72 -0
- package/src/ui/listbox/README.md +115 -0
- package/src/ui/menu/README.md +96 -0
- package/src/ui/popover/README.md +122 -0
- package/src/ui/scroll-lock/README.md +33 -0
- package/src/ui/select/README.md +107 -0
- package/src/ui/server/README.md +90 -0
- package/src/ui/test/README.md +107 -0
- package/src/ui/theme/README.md +103 -0
- package/dist/node-serve.d.ts +0 -2
- package/dist/node-serve.d.ts.map +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# select
|
|
2
|
+
|
|
3
|
+
`Select` is a button-triggered popup value picker backed by `listbox` and `popover`. Use it when the user should choose one stable string value from a finite set.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Option, Select, onSelectChange } from 'remix/ui/select'
|
|
9
|
+
|
|
10
|
+
export function FrameworkSelect() {
|
|
11
|
+
return (
|
|
12
|
+
<Select
|
|
13
|
+
defaultLabel="Select a framework"
|
|
14
|
+
defaultValue="remix"
|
|
15
|
+
name="framework"
|
|
16
|
+
mix={onSelectChange((event) => {
|
|
17
|
+
console.log(event.value, event.label, event.optionId)
|
|
18
|
+
})}
|
|
19
|
+
>
|
|
20
|
+
<Option label="Remix framework" value="remix">
|
|
21
|
+
Remix
|
|
22
|
+
</Option>
|
|
23
|
+
<Option disabled label="React Router framework" value="react-router">
|
|
24
|
+
React Router
|
|
25
|
+
</Option>
|
|
26
|
+
<Option label="React framework" value="react">
|
|
27
|
+
React
|
|
28
|
+
</Option>
|
|
29
|
+
</Select>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use `textValue` when closed-trigger typeahead should match a different string from the visible label.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<Select defaultLabel="Select an environment">
|
|
38
|
+
<Option label="Production environment" value="production">
|
|
39
|
+
Production
|
|
40
|
+
</Option>
|
|
41
|
+
<Option label="Staging environment" textValue="beta" value="staging">
|
|
42
|
+
Staging
|
|
43
|
+
</Option>
|
|
44
|
+
</Select>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use the lower-level primitives when the trigger or popup structure needs to be owned by another component. Keep the same provider, trigger, popover, list, option, and hidden-input relationship.
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import type { Handle } from 'remix/ui'
|
|
51
|
+
import * as button from 'remix/ui/button'
|
|
52
|
+
import * as listbox from 'remix/ui/listbox'
|
|
53
|
+
import * as popover from 'remix/ui/popover'
|
|
54
|
+
import * as select from 'remix/ui/select'
|
|
55
|
+
|
|
56
|
+
function SelectValue(handle: Handle) {
|
|
57
|
+
let context = handle.context.get(select.Context)
|
|
58
|
+
|
|
59
|
+
return () => <span mix={button.labelStyle}>{context.displayedLabel}</span>
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function IssueTypeSelect() {
|
|
63
|
+
return () => (
|
|
64
|
+
<select.Context defaultLabel="Select a type" name="issueType">
|
|
65
|
+
<button type="button" mix={[button.baseStyle, select.triggerStyle, select.trigger()]}>
|
|
66
|
+
<SelectValue />
|
|
67
|
+
</button>
|
|
68
|
+
<popover.Context>
|
|
69
|
+
<div mix={[popover.surfaceStyle, select.popover()]}>
|
|
70
|
+
<div mix={[popover.contentStyle, listbox.listStyle, select.list()]}>
|
|
71
|
+
<div mix={[listbox.optionStyle, select.option({ label: 'Bug', value: 'bug' })]}>
|
|
72
|
+
Bug
|
|
73
|
+
</div>
|
|
74
|
+
<div mix={[listbox.optionStyle, select.option({ label: 'Feature', value: 'feature' })]}>
|
|
75
|
+
Feature
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</popover.Context>
|
|
80
|
+
<input mix={select.hiddenInput()} />
|
|
81
|
+
</select.Context>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## `select.*`
|
|
87
|
+
|
|
88
|
+
- `Select`: composed trigger, popover, listbox, option list, and optional hidden input for form participation. Accepts `defaultLabel`, `defaultValue`, `disabled`, `name`, and button props.
|
|
89
|
+
- `Option`: option wrapper that renders the standard check glyph and label slot. Accepts `label`, `value`, optional `disabled`, and optional `textValue`.
|
|
90
|
+
- `onSelectChange(...)`: event mixin for the bubbling `SelectChangeEvent`.
|
|
91
|
+
- `Context`, `trigger()`, `popover()`, `list()`, `option(...)`, and `hiddenInput()`: lower-level composition primitives.
|
|
92
|
+
- `triggerStyle`: standard select trigger style.
|
|
93
|
+
- `SelectChangeEvent`: event with `value`, `label`, and `optionId`.
|
|
94
|
+
- `SelectProps`, `SelectContextProps`, and `SelectOptionProps`: public TypeScript props for the composed and lower-level APIs.
|
|
95
|
+
|
|
96
|
+
## Behavior Notes
|
|
97
|
+
|
|
98
|
+
- `defaultLabel` is displayed before selection settles. `defaultValue` selects the matching option without replacing the trigger label until a new selection commits.
|
|
99
|
+
- `Option.label` is the committed display label and event label. `children` are the rendered option contents.
|
|
100
|
+
- Click, `ArrowDown`, and `ArrowUp` open the popup. Focus moves into the list and Escape restores focus to the trigger through popover behavior.
|
|
101
|
+
- Reopening highlights the current selected value.
|
|
102
|
+
- The popup min-width syncs to the trigger width before opening.
|
|
103
|
+
- Closed-trigger typeahead selects a matching option immediately and supports option `textValue`.
|
|
104
|
+
- Selecting an option flashes it with `data-select-flash`, waits for the close transition and label delay, updates the displayed label, and dispatches `SelectChangeEvent`.
|
|
105
|
+
- Selecting the already-selected value updates state but does not dispatch a change event.
|
|
106
|
+
- `SelectChangeEvent` bubbles from the trigger when a trigger exists. It includes `value`, `label`, and `optionId`.
|
|
107
|
+
- Passing `name` renders a hidden input so the selected value participates in `FormData`; disabled selects disable the trigger and hidden input.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Server
|
|
2
|
+
|
|
3
|
+
Remix UI can render to HTML on the server using two APIs:
|
|
4
|
+
|
|
5
|
+
- `renderToString` - Returns a complete HTML string. Simple, but buffers the entire response.
|
|
6
|
+
- `renderToStream` - Returns a `ReadableStream<Uint8Array>`. Sends the initial HTML immediately and streams frame content as it resolves.
|
|
7
|
+
|
|
8
|
+
Both are exported from `remix/ui/server`.
|
|
9
|
+
|
|
10
|
+
## renderToString
|
|
11
|
+
|
|
12
|
+
Renders a component tree to a complete HTML string. Use this when you need the full output before responding (e.g., generating static pages or embedding HTML in an email).
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { renderToString } from 'remix/ui/server'
|
|
16
|
+
|
|
17
|
+
let html = await renderToString(<App />)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## renderToStream
|
|
21
|
+
|
|
22
|
+
Renders a component tree to a streaming response. The initial HTML is sent immediately. Any `<Frame>` components with a `fallback` prop will render the fallback first, then stream the resolved content as it becomes available.
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { renderToStream } from 'remix/ui/server'
|
|
26
|
+
|
|
27
|
+
let stream = renderToStream(<App />, {
|
|
28
|
+
frameSrc: request.url,
|
|
29
|
+
signal: request.signal,
|
|
30
|
+
resolveFrame(src, _target, context) {
|
|
31
|
+
let frameUrl = new URL(src, context?.currentFrameSrc ?? request.url)
|
|
32
|
+
return fetchHtml(frameUrl)
|
|
33
|
+
},
|
|
34
|
+
onError(error) {
|
|
35
|
+
console.error(error)
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return new Response(stream, {
|
|
40
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' },
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Options
|
|
45
|
+
|
|
46
|
+
- **`frameSrc`** - Seeds SSR frame state for the current render. When provided, server-rendered components can read `handle.frame.src` and `handle.frames.top.src` during SSR.
|
|
47
|
+
- **`topFrameSrc`** - Overrides the root frame URL used for `handle.frames.top.src`. This is mainly useful when calling `renderToStream()` from inside `resolveFrame()` for a nested frame render.
|
|
48
|
+
- **`signal`** - Cancels pending server rendering work. Pass `request.signal` so client disconnects can stop unresolved frame work without invoking `onError` for the disconnect itself.
|
|
49
|
+
- **`resolveFrame(src, target, context)`** - Called when a `<Frame>` needs its content. Return a string of HTML, a `ReadableStream<Uint8Array>`, or a promise of either. `context.currentFrameSrc` is the URL for the frame that contains the `<Frame>`, and `context.topFrameSrc` is the outer document URL. Required if your component tree contains `<Frame>` elements.
|
|
50
|
+
- **`onError(error)`** - Called when a rendering error occurs. If not provided, the stream rejects with the error.
|
|
51
|
+
|
|
52
|
+
When you render nested frame responses with `renderToStream()` inside `resolveFrame()`, pass `frameSrc` for the frame being rendered and carry `topFrameSrc` forward from the parent context. That preserves `handle.frames.top.src` across the whole SSR frame tree.
|
|
53
|
+
|
|
54
|
+
### Streaming behavior
|
|
55
|
+
|
|
56
|
+
When the stream encounters a `<Frame>` component:
|
|
57
|
+
|
|
58
|
+
- **Without `fallback`** (blocking): The frame content is awaited before the initial HTML chunk is sent. The resolved content appears inline.
|
|
59
|
+
- **With `fallback`** (non-blocking): The fallback is rendered inline in the initial chunk. Once the frame resolves, a `<template>` element containing the real content is streamed at the end of the response. The client swaps it in automatically.
|
|
60
|
+
|
|
61
|
+
This means the first chunk always contains a complete, renderable page. Slow data sources don't block the initial paint.
|
|
62
|
+
|
|
63
|
+
## Head content
|
|
64
|
+
|
|
65
|
+
To render content into the document head during SSR, use an explicit `<head>` element:
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
function ProductPage() {
|
|
69
|
+
return () => (
|
|
70
|
+
<html>
|
|
71
|
+
<head>
|
|
72
|
+
<title>Product Name</title>
|
|
73
|
+
<meta name="description" content="A great product" />
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<h1>Product Name</h1>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## CSS
|
|
84
|
+
|
|
85
|
+
Components using the `css(...)` mixin through `mix` have their styles collected during rendering and emitted as a single `<style>` tag in the `<head>`. No client-side style injection is needed for server-rendered content.
|
|
86
|
+
|
|
87
|
+
## See Also
|
|
88
|
+
|
|
89
|
+
- [Hydration](https://github.com/remix-run/remix/blob/main/packages/ui/docs/hydration.md) - Making server-rendered components interactive on the client
|
|
90
|
+
- [Frames](https://github.com/remix-run/remix/blob/main/packages/ui/docs/frames.md) - Streaming partial server UI with `<Frame>`
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Test
|
|
2
|
+
|
|
3
|
+
When writing tests, use `root.flush()` to synchronously execute all pending updates and tasks. This ensures the DOM and component state are fully synchronized before making assertions.
|
|
4
|
+
|
|
5
|
+
## Basic Testing Pattern
|
|
6
|
+
|
|
7
|
+
The main use case is flushing after events that call `handle.update()`. Since updates are asynchronous, you need to flush to ensure the DOM reflects the changes:
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
function Counter(handle: Handle) {
|
|
11
|
+
let count = 0
|
|
12
|
+
|
|
13
|
+
return () => (
|
|
14
|
+
<button
|
|
15
|
+
mix={[
|
|
16
|
+
on('click', () => {
|
|
17
|
+
count++
|
|
18
|
+
handle.update()
|
|
19
|
+
}),
|
|
20
|
+
]}
|
|
21
|
+
>
|
|
22
|
+
Count: {count}
|
|
23
|
+
</button>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// In your test
|
|
28
|
+
let container = document.createElement('div')
|
|
29
|
+
let root = createRoot(container)
|
|
30
|
+
|
|
31
|
+
root.render(<Counter />)
|
|
32
|
+
root.flush() // Ensure initial render completes
|
|
33
|
+
|
|
34
|
+
let button = container.querySelector('button')
|
|
35
|
+
button.click() // Triggers handle.update()
|
|
36
|
+
root.flush() // Flush to apply the update
|
|
37
|
+
|
|
38
|
+
expect(container.textContent).toBe('Count: 1')
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Why Flush After Initial Render?
|
|
42
|
+
|
|
43
|
+
You should also flush after the initial `root.render()` to ensure event listeners are attached and the DOM is ready for interaction:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
let root = createRoot(container)
|
|
47
|
+
root.render(<MyComponent />)
|
|
48
|
+
root.flush() // Event listeners now attached
|
|
49
|
+
|
|
50
|
+
// Safe to interact
|
|
51
|
+
container.querySelector('button').click()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Testing Async Operations
|
|
55
|
+
|
|
56
|
+
For components with async operations in `queueTask`, flush after each step:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
function AsyncLoader(handle: Handle) {
|
|
60
|
+
let data: string | null = null
|
|
61
|
+
|
|
62
|
+
handle.queueTask(async (signal) => {
|
|
63
|
+
let response = await fetch('/api/data', { signal })
|
|
64
|
+
let json = await response.json()
|
|
65
|
+
if (signal.aborted) return
|
|
66
|
+
data = json.value
|
|
67
|
+
handle.update()
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
return () => <div>{data ?? 'Loading...'}</div>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// In your test (with mocked fetch)
|
|
74
|
+
let root = createRoot(container)
|
|
75
|
+
root.render(<AsyncLoader />)
|
|
76
|
+
root.flush()
|
|
77
|
+
|
|
78
|
+
expect(container.textContent).toBe('Loading...')
|
|
79
|
+
|
|
80
|
+
// After fetch resolves
|
|
81
|
+
await waitForFetch()
|
|
82
|
+
root.flush()
|
|
83
|
+
|
|
84
|
+
expect(container.textContent).toBe('Expected data')
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Testing Component Removal
|
|
88
|
+
|
|
89
|
+
Use `root.dispose()` to clean up and verify cleanup behavior:
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
let root = createRoot(container)
|
|
93
|
+
root.render(<MyComponent />)
|
|
94
|
+
root.flush()
|
|
95
|
+
|
|
96
|
+
// Verify setup behavior
|
|
97
|
+
expect(container.querySelector('.content')).toBeTruthy()
|
|
98
|
+
|
|
99
|
+
// Remove and verify cleanup
|
|
100
|
+
root.dispose()
|
|
101
|
+
expect(container.innerHTML).toBe('')
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## See Also
|
|
105
|
+
|
|
106
|
+
- [Getting Started](https://github.com/remix-run/remix/blob/main/packages/ui/docs/getting-started.md) - Root methods reference
|
|
107
|
+
- [Handle API](https://github.com/remix-run/remix/blob/main/packages/ui/docs/handle.md) - `handle.queueTask()` behavior
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# theme
|
|
2
|
+
|
|
3
|
+
`theme` provides Remix UI design tokens, theme creation, glyph contracts, and the built-in `RMX_01` preset. Use it to install CSS custom properties once and consume typed token references in component styles.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { createTheme, theme } from 'remix/ui/theme'
|
|
9
|
+
import { css } from 'remix/ui'
|
|
10
|
+
|
|
11
|
+
let Theme = createTheme({
|
|
12
|
+
space: {
|
|
13
|
+
none: '0px',
|
|
14
|
+
px: '1px',
|
|
15
|
+
xs: '2px',
|
|
16
|
+
sm: '4px',
|
|
17
|
+
md: '8px',
|
|
18
|
+
lg: '12px',
|
|
19
|
+
xl: '16px',
|
|
20
|
+
xxl: '24px',
|
|
21
|
+
},
|
|
22
|
+
radius: { none: '0px', sm: '4px', md: '8px', lg: '12px', xl: '16px', full: '9999px' },
|
|
23
|
+
fontFamily: { sans: 'Inter, sans-serif', mono: 'monospace' },
|
|
24
|
+
fontSize: {
|
|
25
|
+
xxxs: '10px',
|
|
26
|
+
xxs: '11px',
|
|
27
|
+
xs: '12px',
|
|
28
|
+
sm: '14px',
|
|
29
|
+
md: '16px',
|
|
30
|
+
lg: '18px',
|
|
31
|
+
xl: '20px',
|
|
32
|
+
xxl: '28px',
|
|
33
|
+
},
|
|
34
|
+
lineHeight: { tight: '1.2', normal: '1.5', relaxed: '1.7' },
|
|
35
|
+
letterSpacing: { tight: '-0.02em', normal: '0', meta: '0.06em', wide: '0.08em' },
|
|
36
|
+
fontWeight: { normal: '400', medium: '500', semibold: '600', bold: '700' },
|
|
37
|
+
control: { height: { sm: '28px', md: '32px', lg: '36px' } },
|
|
38
|
+
surface: { lvl0: '#fff', lvl1: '#f8fafc', lvl2: '#f5f5f5', lvl3: '#f1f5f9', lvl4: '#e9eef6' },
|
|
39
|
+
shadow: { xs: 'none', sm: 'none', md: 'none', lg: 'none', xl: 'none' },
|
|
40
|
+
colors: {
|
|
41
|
+
text: { primary: '#111827', secondary: '#374151', muted: '#6b7280', link: '#2563eb' },
|
|
42
|
+
border: { subtle: '#e5e7eb', default: '#d1d5db', strong: '#9ca3af' },
|
|
43
|
+
focus: { ring: '#3b82f6' },
|
|
44
|
+
overlay: { scrim: 'rgb(0 0 0 / 0.45)' },
|
|
45
|
+
action: {
|
|
46
|
+
primary: {
|
|
47
|
+
background: '#2563eb',
|
|
48
|
+
backgroundHover: '#1d4ed8',
|
|
49
|
+
backgroundActive: '#1e40af',
|
|
50
|
+
foreground: '#fff',
|
|
51
|
+
border: '#2563eb',
|
|
52
|
+
},
|
|
53
|
+
secondary: {
|
|
54
|
+
background: '#fff',
|
|
55
|
+
backgroundHover: '#f8fafc',
|
|
56
|
+
backgroundActive: '#f1f5f9',
|
|
57
|
+
foreground: '#111827',
|
|
58
|
+
border: '#d1d5db',
|
|
59
|
+
},
|
|
60
|
+
danger: {
|
|
61
|
+
background: '#dc2626',
|
|
62
|
+
backgroundHover: '#b91c1c',
|
|
63
|
+
backgroundActive: '#991b1b',
|
|
64
|
+
foreground: '#fff',
|
|
65
|
+
border: '#dc2626',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
let card = css({
|
|
72
|
+
backgroundColor: theme.surface.lvl0,
|
|
73
|
+
color: theme.colors.text.primary,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
function Layout() {
|
|
77
|
+
return (
|
|
78
|
+
<body>
|
|
79
|
+
<Theme />
|
|
80
|
+
<article mix={card}>Project status</article>
|
|
81
|
+
</body>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## `theme.*`
|
|
87
|
+
|
|
88
|
+
- `theme`: typed CSS variable reference contract, such as `theme.space.md` and `theme.colors.text.primary`.
|
|
89
|
+
- `createTheme(values, options?)`: creates a style component with `cssText`, `selector`, `values`, `vars`, and `Style`.
|
|
90
|
+
- `RMX_01`: built-in theme component.
|
|
91
|
+
- `RMX_01_GLYPHS`: built-in glyph sheet component.
|
|
92
|
+
- `glyphContract` and `glyphNames`: stable glyph ids and supported glyph names.
|
|
93
|
+
- `ThemeValues`, `ThemeVars`, `ThemeComponent`, `ThemeStyleProps`, `CreateThemeOptions`, and `ThemeMix`: public TypeScript types for custom themes.
|
|
94
|
+
- `GlyphName`, `GlyphSymbol`, and `GlyphValues`: public TypeScript types for glyph contracts.
|
|
95
|
+
|
|
96
|
+
## Behavior Notes
|
|
97
|
+
|
|
98
|
+
- `theme` values are CSS variable references, not raw token values.
|
|
99
|
+
- `createTheme` serializes token values into CSS custom properties and renders a `<style data-rmx-theme>` tag.
|
|
100
|
+
- The default selector is `:root`; pass `selector` for scoped themes.
|
|
101
|
+
- The base reset is included by default, emitted in `rmx-reset`, and can be disabled with `reset: false`.
|
|
102
|
+
- The built-in components consume this token contract through their style mixins.
|
|
103
|
+
- Render `<RMX_01 />` and `<RMX_01_GLYPHS />` once when using the built-in theme and glyph preset.
|
package/dist/node-serve.d.ts
DELETED
package/dist/node-serve.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"node-serve.d.ts","sourceRoot":"","sources":["../src/node-serve.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA"}
|