@satinhq/kit 0.1.0-beta.0 → 0.1.0-beta.1
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/NOTICE +1 -1
- package/dist/acknowledgements/inventory.json +1 -1
- package/dist/docs/swiftui-reference.md +2 -2
- package/dist/glass/GlassPresentation.d.ts +1 -0
- package/dist/glass/GlassPresentation.js +4 -1
- package/dist/glass/TabBar.js +7 -0
- package/dist/glass/lens/tabGlyphColours.d.ts +2 -2
- package/dist/glass/lens/tabGlyphColours.js +5 -4
- package/dist/glass/liquidContext.d.ts +1 -0
- package/dist/glass/webgpu/productionPrepare.js +2 -1
- package/dist/styles.css +6 -6
- package/package.json +2 -1
package/NOTICE
CHANGED
|
@@ -12,7 +12,7 @@ is a separately installed build dependency. Consumer Vite builds emit NOTICE.txt
|
|
|
12
12
|
and licenses.json from their actual emitted module graph, including runtime peers.
|
|
13
13
|
Development dependencies are not assumed to be bundled.
|
|
14
14
|
|
|
15
|
-
## Satin 0.1.0-beta.
|
|
15
|
+
## Satin 0.1.0-beta.1
|
|
16
16
|
|
|
17
17
|
License: MIT
|
|
18
18
|
Source: https://opensource.org/license/mit
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "Satin",
|
|
4
|
-
"version": "0.1.0-beta.
|
|
4
|
+
"version": "0.1.0-beta.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"source": "https://opensource.org/license/mit",
|
|
7
7
|
"text": "MIT License\n\nCopyright (c) 2026 Satin contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
|
|
@@ -1883,7 +1883,7 @@ export function DraftEditor() {
|
|
|
1883
1883
|
- `@satinhq/kit:6b1393b088849383b4d58af841b53afabf734a131abd2a0c51e5e47d76a031ee`
|
|
1884
1884
|
- `@satinhq/kit/vite:63ab5323f1fdbfe3425716de812e63889353f0a7252fdb379ddd29f0113c6c7b`
|
|
1885
1885
|
- `@satinhq/kit/install:85c36af3f6d918e999f65db362675d8982468350930a540177d3d9809c88ca01`
|
|
1886
|
-
- `@satinhq/kit/internal:
|
|
1886
|
+
- `@satinhq/kit/internal:39d720eaa8548f9bf1a0c01ef5868efc9b437c21e18114ef50436047fdbd4e80`
|
|
1887
1887
|
- `@satinhq/kit/unstable:09d854e967c086ed0eaa8b3decbbd326306e1f35e493b79cc1f375060319a840`
|
|
1888
1888
|
- `@satinhq/kit/server:1b9db029ea048edc062313e7116510843dab71d9a5630842f778bc45736e3990`
|
|
1889
1889
|
- `@satinhq/kit/testing:cb9036de4e4b3df41671c759c0fc123b059bd412849ac0796479ead545fa8728`
|
|
@@ -1892,4 +1892,4 @@ export function DraftEditor() {
|
|
|
1892
1892
|
|
|
1893
1893
|
## Framework source fingerprint
|
|
1894
1894
|
|
|
1895
|
-
SHA-256 of sorted TS/TSX/CSS source paths and bytes, excluding tests:
|
|
1895
|
+
SHA-256 of sorted TS/TSX/CSS source paths and bytes, excluding tests: b5ce591e73a0ec3a6d860cfa0434aa456a6128aa55251eed3e46b4e35ad8d223
|
|
@@ -970,7 +970,10 @@ export function GlassPresentation({ consumer }) {
|
|
|
970
970
|
runtimeRef.current?.selectTabAnimated(next);
|
|
971
971
|
}, children: tabNames.map((label, index) => (_jsxs("button", { className: index === selectedTab
|
|
972
972
|
? 'satin-lens-tab-item satin-lens-is-selected'
|
|
973
|
-
: 'satin-lens-tab-item', style:
|
|
973
|
+
: 'satin-lens-tab-item', style: {
|
|
974
|
+
...tabGlyphStyle(appearance, contentPage, index, consumer?.tabs?.tint),
|
|
975
|
+
'--satin-tab-tint': consumer?.tabs?.tint,
|
|
976
|
+
}, type: "button", role: "tab", "data-tab-index": index, "data-satin-tab-role": consumer?.tabs?.items[index]?.role, id: consumer?.tabs?.items[index]?.tabId, "aria-controls": consumer?.tabs?.items[index]?.panelId, disabled: consumer?.tabs?.items[index]?.disabled, "aria-label": consumer?.tabs?.items[index]?.accessibilityLabel ??
|
|
974
977
|
(tabBarPlacement === 'top' && consumer?.tabs?.items[index]?.role === 'search'
|
|
975
978
|
? typeof label === 'string'
|
|
976
979
|
? label
|
package/dist/glass/TabBar.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useControlStyle } from '../public/controlStyle.js';
|
|
2
3
|
import { orderedTabItems, TopTabLabel } from '../tabs/presentation.js';
|
|
3
4
|
import { handleTabKeyDown } from '../tabs/keyboard.js';
|
|
4
5
|
import { readDeviceIdiom } from '../layout/deviceIdiom.js';
|
|
@@ -19,6 +20,7 @@ import { useGlassMaterialContext } from './context.js';
|
|
|
19
20
|
import { resolveTabBarModel, TabBarAccessoryContext } from './tabBarModel.js';
|
|
20
21
|
import {} from './tokens.js';
|
|
21
22
|
export function TabBar({ className, adaptive = true, onShowSidebar, items: declaredItems, onSelect, selected, style, variant = 'regular', ...props }) {
|
|
23
|
+
const { tint } = useControlStyle();
|
|
22
24
|
const liquid = useContext(MaterialEffectContext);
|
|
23
25
|
const layoutClass = useLayoutClass();
|
|
24
26
|
const metrics = useSafeAreaMetrics();
|
|
@@ -83,6 +85,7 @@ export function TabBar({ className, adaptive = true, onShowSidebar, items: decla
|
|
|
83
85
|
onSelect,
|
|
84
86
|
adaptive,
|
|
85
87
|
variant,
|
|
88
|
+
tint,
|
|
86
89
|
insetHost: elementRef.current ?? undefined,
|
|
87
90
|
placement: 'top',
|
|
88
91
|
itemFrames,
|
|
@@ -96,6 +99,7 @@ export function TabBar({ className, adaptive = true, onShowSidebar, items: decla
|
|
|
96
99
|
onSelect,
|
|
97
100
|
adaptive,
|
|
98
101
|
variant,
|
|
102
|
+
tint,
|
|
99
103
|
liquidTop,
|
|
100
104
|
itemFrames,
|
|
101
105
|
]);
|
|
@@ -108,6 +112,7 @@ export function TabBar({ className, adaptive = true, onShowSidebar, items: decla
|
|
|
108
112
|
onSelect,
|
|
109
113
|
adaptive,
|
|
110
114
|
variant,
|
|
115
|
+
tint,
|
|
111
116
|
insetHost: elementRef.current ?? undefined,
|
|
112
117
|
intrinsicWidth,
|
|
113
118
|
});
|
|
@@ -120,6 +125,7 @@ export function TabBar({ className, adaptive = true, onShowSidebar, items: decla
|
|
|
120
125
|
onSelect,
|
|
121
126
|
adaptive,
|
|
122
127
|
variant,
|
|
128
|
+
tint,
|
|
123
129
|
sidebar,
|
|
124
130
|
intrinsicWidth,
|
|
125
131
|
]);
|
|
@@ -146,6 +152,7 @@ export function TabBar({ className, adaptive = true, onShowSidebar, items: decla
|
|
|
146
152
|
const tabBarStyle = {
|
|
147
153
|
...style,
|
|
148
154
|
...(sidebar ? sidebarCssTokens : {}),
|
|
155
|
+
'--satin-tab-tint': tint,
|
|
149
156
|
'--satin-tab-count': items.length,
|
|
150
157
|
'--satin-tab-selection-offset': `${selectedIndex * 100}%`,
|
|
151
158
|
'--satin-tab-selected-index': selectedIndex,
|
|
@@ -3,13 +3,13 @@ import type { Appearance } from './theme.js';
|
|
|
3
3
|
* glass mirror; scrolling needs no new GPU readback and no fixture-name lookup.
|
|
4
4
|
* The chroma correction is a first-order fit, pending textured ink acceptance.
|
|
5
5
|
*/
|
|
6
|
-
export declare function tabGlyphContextStyle(appearance: Appearance, rgb: readonly number[]): {
|
|
6
|
+
export declare function tabGlyphContextStyle(appearance: Appearance, rgb: readonly number[], tint?: string): {
|
|
7
7
|
'--tab-selected-icon': string;
|
|
8
8
|
'--tab-selected-label': string;
|
|
9
9
|
'--tab-unselected-icon': string;
|
|
10
10
|
'--tab-unselected-label': string;
|
|
11
11
|
};
|
|
12
|
-
export declare function tabGlyphStyle(appearance: Appearance, _background: string, _index: number): {
|
|
12
|
+
export declare function tabGlyphStyle(appearance: Appearance, _background: string, _index: number, tint?: string): {
|
|
13
13
|
'--tab-selected-icon': string;
|
|
14
14
|
'--tab-selected-label': string;
|
|
15
15
|
'--tab-unselected-icon': string;
|
|
@@ -15,7 +15,7 @@ function neutral(appearance, k, kind) {
|
|
|
15
15
|
* glass mirror; scrolling needs no new GPU readback and no fixture-name lookup.
|
|
16
16
|
* The chroma correction is a first-order fit, pending textured ink acceptance.
|
|
17
17
|
*/
|
|
18
|
-
export function tabGlyphContextStyle(appearance, rgb) {
|
|
18
|
+
export function tabGlyphContextStyle(appearance, rgb, tint) {
|
|
19
19
|
const k = luma(rgb);
|
|
20
20
|
const chroma = rgb.reduce((sum, v, i) => sum + (v - k) * axis[i], 0) / norm;
|
|
21
21
|
const colour = (kind) => {
|
|
@@ -24,7 +24,8 @@ export function tabGlyphContextStyle(appearance, rgb) {
|
|
|
24
24
|
.map((v, i) => Math.max(0, Math.min(255, v + chroma * (fit[appearance][2][kind][i] - blueNeutral[i]))).toFixed(3))
|
|
25
25
|
.join(' ')})`;
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
// Explicit author tint is a semantic colour, not the system-blue vibrancy fit.
|
|
28
|
+
const selected = tint || colour('selected'), unselected = colour('unselected');
|
|
28
29
|
return {
|
|
29
30
|
'--tab-selected-icon': selected,
|
|
30
31
|
'--tab-selected-label': selected,
|
|
@@ -32,6 +33,6 @@ export function tabGlyphContextStyle(appearance, rgb) {
|
|
|
32
33
|
'--tab-unselected-label': unselected,
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
|
-
export function tabGlyphStyle(appearance, _background, _index) {
|
|
36
|
-
return tabGlyphContextStyle(appearance, appearance === 'light' ? [1, 1, 1] : [0, 0, 0]);
|
|
36
|
+
export function tabGlyphStyle(appearance, _background, _index, tint) {
|
|
37
|
+
return tabGlyphContextStyle(appearance, appearance === 'light' ? [1, 1, 1] : [0, 0, 0], tint);
|
|
37
38
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { GlassRegionRegistry } from './regionRegistry.js';
|
|
2
2
|
import type { TabBarProps, TabItemFrame } from './TabBar.js';
|
|
3
3
|
export type RegisteredTabBar = TabBarProps & Readonly<{
|
|
4
|
+
tint?: string;
|
|
4
5
|
insetHost?: HTMLElement;
|
|
5
6
|
intrinsicWidth?: boolean;
|
|
6
7
|
/** 'top': the regular-width iPad bar, laid out by `itemFrames` inside `insetHost`. */
|
|
@@ -736,7 +736,8 @@ function applyTabGlyphContext(dock, elements, context, geometry, appearance) {
|
|
|
736
736
|
const sample = context.sample(dock.frameX + 10.5 + ((dock.frameWidth - 20) / tabs.length) * (i + 0.5), dock.frameY + dock.frameHeight / 2 + elements.scroller.scrollTop, TAB_CONTEXT_RADIUS, elements.scroller.scrollTop, elements.scroller.scrollTop + geometry.height);
|
|
737
737
|
if (!sample)
|
|
738
738
|
return;
|
|
739
|
-
|
|
739
|
+
const tint = getComputedStyle(tab).getPropertyValue('--satin-tab-tint').trim();
|
|
740
|
+
for (const [property, value] of Object.entries(tabGlyphContextStyle(appearance, sample.rgb, tint)))
|
|
740
741
|
tab.style.setProperty(property, value);
|
|
741
742
|
});
|
|
742
743
|
}
|
package/dist/styles.css
CHANGED
|
@@ -349,7 +349,7 @@ body[data-satin-document='true'],
|
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
[data-satin-tab-item='true'][data-satin-tab-selected='true'] {
|
|
352
|
-
color: rgb(0 122 255);
|
|
352
|
+
color: var(--satin-tab-tint, rgb(0 122 255));
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
[data-satin-tab-icon='true'] {
|
|
@@ -387,7 +387,7 @@ body[data-satin-document='true'],
|
|
|
387
387
|
}
|
|
388
388
|
:where(html[data-satin-appearance='dark'])
|
|
389
389
|
[data-satin-tab-item='true'][data-satin-tab-selected='true'] {
|
|
390
|
-
color: rgb(64 156 255);
|
|
390
|
+
color: var(--satin-tab-tint, rgb(64 156 255));
|
|
391
391
|
}
|
|
392
392
|
:where(html[data-satin-appearance='dark']) [data-satin-tab-selection='true'] {
|
|
393
393
|
background: rgb(98 99 107 / 34%);
|
|
@@ -1129,7 +1129,7 @@ body[data-satin-document='true'],
|
|
|
1129
1129
|
color: inherit;
|
|
1130
1130
|
}
|
|
1131
1131
|
[data-satin-tab-placement='top'] [data-satin-tab-selected='true'] {
|
|
1132
|
-
color: var(--satin-sidebar-light-tabTint);
|
|
1132
|
+
color: var(--satin-tab-tint, var(--satin-sidebar-light-tabTint));
|
|
1133
1133
|
background: var(--satin-sidebar-light-tabSelection);
|
|
1134
1134
|
}
|
|
1135
1135
|
[data-satin-tab-placement='top'] [data-satin-tab-label] {
|
|
@@ -1162,7 +1162,7 @@ body[data-satin-document='true'],
|
|
|
1162
1162
|
:where(html[data-satin-appearance='dark'])
|
|
1163
1163
|
[data-satin-tab-placement='top']
|
|
1164
1164
|
[data-satin-tab-selected='true'] {
|
|
1165
|
-
color: var(--satin-sidebar-dark-tabTint);
|
|
1165
|
+
color: var(--satin-tab-tint, var(--satin-sidebar-dark-tabTint));
|
|
1166
1166
|
background: var(--satin-sidebar-dark-tabSelection);
|
|
1167
1167
|
}
|
|
1168
1168
|
|
|
@@ -2261,7 +2261,7 @@ body[data-satin-document='true'],
|
|
|
2261
2261
|
white-space: nowrap;
|
|
2262
2262
|
}
|
|
2263
2263
|
[data-satin-tab-layout='top'] .satin-lens-tab-item.satin-lens-is-selected small {
|
|
2264
|
-
color: var(--satin-sidebar-light-tabTint);
|
|
2264
|
+
color: var(--satin-tab-tint, var(--satin-sidebar-light-tabTint));
|
|
2265
2265
|
font-weight: var(--satin-sidebar-tabSelectedFontWeight);
|
|
2266
2266
|
}
|
|
2267
2267
|
:where(html[data-satin-appearance='dark'])
|
|
@@ -2274,7 +2274,7 @@ body[data-satin-document='true'],
|
|
|
2274
2274
|
[data-satin-tab-layout='top']
|
|
2275
2275
|
.satin-lens-tab-item.satin-lens-is-selected
|
|
2276
2276
|
small {
|
|
2277
|
-
color: var(--satin-sidebar-dark-tabTint);
|
|
2277
|
+
color: var(--satin-tab-tint, var(--satin-sidebar-dark-tabTint));
|
|
2278
2278
|
}
|
|
2279
2279
|
[data-satin-tab-layout='compact'] .satin-lens-tab-items .satin-lens-tab-icon {
|
|
2280
2280
|
width: 24px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@satinhq/kit",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Opinionated single-target framework for agent-generated personal iOS Home Screen apps.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"bin": {
|
|
108
108
|
"satin": "./bin/satin.mjs"
|
|
109
109
|
},
|
|
110
|
+
"homepage": "https://satin.build",
|
|
110
111
|
"scripts": {
|
|
111
112
|
"build": "node scripts/build.mjs",
|
|
112
113
|
"typecheck": "tsc -p tsconfig.json --pretty false",
|