@foldjs/svelte 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fold.js contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,191 @@
1
- # Temporary Holding Version
1
+ # fold.js
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm](https://img.shields.io/npm/v/foldjs?color=5b4bff)](https://www.npmjs.com/package/foldjs)
4
+ [![gzip size](https://img.shields.io/bundlejs/size/foldjs?label=gzip)](https://bundlejs.com/?q=foldjs)
5
+ [![license](https://img.shields.io/npm/l/foldjs)](LICENSE)
6
+
7
+ **Make any web app foldable-ready.** Hinge-aware layouts for foldable phones — in React, Vue, Svelte, Solid, Angular… or plain HTML.
8
+
9
+ ### [▶ Live demo](https://christophe77.github.io/foldjs/) — no foldable needed, the simulator is built in.
10
+
11
+ ![fold.js switching between flat, book and tabletop postures](https://raw.githubusercontent.com/christophe77/foldjs/main/docs/demo.gif)
12
+
13
+ - 🪟 **Two-pane layouts** that put each pane on its own side of the hinge
14
+ - 📐 **Posture detection**: `flat`, `book`, `tabletop`, `folded`
15
+ - 🧪 **Built-in foldable simulator** — no device, no DevTools setup
16
+ - 🧩 **Works everywhere**: framework-agnostic core, thin adapters, Web Components, CSS-only layer
17
+ - 🪶 **~2 kB** min+gzip core, zero dependencies, SSR-safe, TypeScript
18
+
19
+ Built on the web standards shipping in Chromium: [CSS Viewport Segments](https://developer.mozilla.org/en-US/docs/Web/API/Viewport_segments_API) and the [Device Posture API](https://developer.mozilla.org/en-US/docs/Web/API/Device_Posture_API).
20
+
21
+ ---
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm i foldjs # core, CSS, Web Components, simulator
27
+ npm i @foldjs/react # or @foldjs/vue, @foldjs/svelte, @foldjs/solid
28
+ ```
29
+
30
+ ## React
31
+
32
+ ```tsx
33
+ import { TwoPane, FoldWhen, FoldDevtools, useFold } from "@foldjs/react";
34
+
35
+ export function Inbox() {
36
+ const { posture, hinge } = useFold();
37
+
38
+ return (
39
+ <>
40
+ <TwoPane
41
+ primary={<MailList />}
42
+ secondary={<MailDetail />}
43
+ fallback="stack" // single screen: "stack" | "primary" | "secondary"
44
+ />
45
+ <FoldWhen posture="tabletop">
46
+ <PlayerControls />
47
+ </FoldWhen>
48
+ {import.meta.env.DEV && <FoldDevtools initial="book" />}
49
+ </>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ## Vue
55
+
56
+ ```vue
57
+ <script setup>
58
+ import { TwoPane, FoldWhen, useFold } from "@foldjs/vue";
59
+ const fold = useFold(); // fold.value.posture
60
+ </script>
61
+
62
+ <template>
63
+ <TwoPane fallback="stack">
64
+ <template #primary><MailList /></template>
65
+ <template #secondary><MailDetail /></template>
66
+ </TwoPane>
67
+ </template>
68
+ ```
69
+
70
+ ## Svelte
71
+
72
+ ```svelte
73
+ <script>
74
+ import { fold, twoPane, foldWhen } from "@foldjs/svelte";
75
+ </script>
76
+
77
+ <div use:twoPane={{ fallback: "stack" }}>
78
+ <div data-pane="primary"><MailList /></div>
79
+ <div data-pane="secondary"><MailDetail /></div>
80
+ </div>
81
+
82
+ <p>Posture: {$fold.posture}</p>
83
+ <div use:foldWhen={"tabletop"}>Tabletop only</div>
84
+ ```
85
+
86
+ ## Solid
87
+
88
+ ```tsx
89
+ import { createFold, twoPane } from "@foldjs/solid";
90
+
91
+ const fold = createFold(); // fold().posture
92
+
93
+ <div use:twoPane={{ fallback: "stack" }}>
94
+ <div data-pane="primary"><MailList /></div>
95
+ <div data-pane="secondary"><MailDetail /></div>
96
+ </div>
97
+ ```
98
+
99
+ ## Web Components (Angular, Lit, Astro, htmx, plain HTML…)
100
+
101
+ ```html
102
+ <script type="module">import "foldjs/elements";</script>
103
+
104
+ <fold-two-pane fallback="stack">
105
+ <div slot="primary">List</div>
106
+ <div slot="secondary">Detail</div>
107
+ </fold-two-pane>
108
+
109
+ <fold-when posture="tabletop book">Only on a split screen</fold-when>
110
+ ```
111
+
112
+ ## CSS only
113
+
114
+ ```js
115
+ import "foldjs/css";
116
+ import { init } from "foldjs";
117
+ init(); // optional: enables the simulator and non-native browsers
118
+ ```
119
+
120
+ ```html
121
+ <div class="fold-two-pane">
122
+ <div class="fold-primary">List</div>
123
+ <div class="fold-secondary">Detail</div>
124
+ </div>
125
+ <div class="fold-only-tabletop">Tabletop only</div>
126
+ ```
127
+
128
+ Variables available on `<html>`: `--fold-hinge-x|y|width|height`, `--fold-segment-0-width|height`, `--fold-segment-1-width|height`.
129
+ Attributes: `data-fold-posture`, `data-fold-spanning`.
130
+
131
+ ## The simulator
132
+
133
+ ```js
134
+ import { mountDevtools } from "foldjs/devtools";
135
+ mountDevtools({ initial: "book", position: "bottom-right", hingeSize: 24 });
136
+ ```
137
+
138
+ Switch between **Device / Flat / Book / Tabletop** from the floating panel, or press **Alt + Shift + F**.
139
+ Or drive it from code (tests, demos, Storybook): `simulate({ posture: "tabletop" })`, `simulate(null)`.
140
+
141
+ ## Core API
142
+
143
+ ```ts
144
+ import { getFold, subscribe, simulate, twoPaneLayout, bindTwoPane } from "foldjs";
145
+
146
+ getFold();
147
+ // {
148
+ // posture: "book", // "flat" | "book" | "tabletop" | "folded"
149
+ // spanning: "columns", // "none" | "columns" | "rows"
150
+ // isSpanned: true,
151
+ // segments: [{ x, y, width, height }, …],
152
+ // hinge: { x, y, width, height },
153
+ // devicePosture: "folded", // raw Device Posture API value
154
+ // viewport: { width, height },
155
+ // simulated: false
156
+ // }
157
+
158
+ const off = subscribe((state) => console.log(state.posture));
159
+ ```
160
+
161
+ Writing an adapter for another framework? `subscribe` + `getFold` are all you need; `twoPaneLayout(state)` returns the styles every built-in adapter uses.
162
+
163
+ ## Browser support
164
+
165
+ | | Native | With `foldjs` |
166
+ |---|---|---|
167
+ | Chrome / Edge on Android foldables | ✅ Viewport Segments + Device Posture | ✅ |
168
+ | Samsung Internet, other browsers | — | ✅ Single-screen fallback, simulator |
169
+ | Desktop | — | ✅ Simulator |
170
+
171
+ ## Repository
172
+
173
+ ```
174
+ packages/core foldjs core, CSS, Web Components, simulator
175
+ packages/react @foldjs/react
176
+ packages/vue @foldjs/vue
177
+ packages/svelte @foldjs/svelte
178
+ packages/solid @foldjs/solid
179
+ apps/demo demo site (Vite + React)
180
+ ```
181
+
182
+ ```bash
183
+ npm install
184
+ npm run dev # demo on http://localhost:5173
185
+ npm test
186
+ npm run build
187
+ ```
188
+
189
+ ## License
190
+
191
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ fold: () => fold,
24
+ foldWhen: () => foldWhen,
25
+ mountDevtools: () => import_devtools.mountDevtools,
26
+ simulate: () => import_foldjs2.simulate,
27
+ twoPane: () => twoPane
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+ var import_store = require("svelte/store");
31
+ var import_foldjs = require("foldjs");
32
+ var import_foldjs2 = require("foldjs");
33
+ var import_devtools = require("foldjs/devtools");
34
+ var fold = (0, import_store.readable)((0, import_foldjs.getFold)(), (set) => {
35
+ set((0, import_foldjs.getFold)());
36
+ return (0, import_foldjs.subscribe)(set);
37
+ });
38
+ function twoPane(node, options = {}) {
39
+ return (0, import_foldjs.bindTwoPane)(node, options);
40
+ }
41
+ function foldWhen(node, posture) {
42
+ let wanted = posture;
43
+ const paint = () => {
44
+ const list = Array.isArray(wanted) ? wanted : [wanted];
45
+ node.hidden = !list.includes((0, import_foldjs.getFold)().posture);
46
+ };
47
+ const unsubscribe = (0, import_foldjs.subscribe)(paint);
48
+ paint();
49
+ return {
50
+ update(next) {
51
+ wanted = next;
52
+ paint();
53
+ },
54
+ destroy: unsubscribe
55
+ };
56
+ }
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ fold,
60
+ foldWhen,
61
+ mountDevtools,
62
+ simulate,
63
+ twoPane
64
+ });
@@ -0,0 +1,24 @@
1
+ import { Readable } from 'svelte/store';
2
+ import { FoldState, Posture, TwoPaneOptions } from 'foldjs';
3
+ export { FoldState, Posture, Rect, Spanning, simulate } from 'foldjs';
4
+ export { mountDevtools } from 'foldjs/devtools';
5
+
6
+ /** Live foldable state: `$fold.posture`, `$fold.hinge`… */
7
+ declare const fold: Readable<FoldState>;
8
+ /**
9
+ * <div use:twoPane={{ fallback: "stack" }}>
10
+ * <div data-pane="primary">…</div>
11
+ * <div data-pane="secondary">…</div>
12
+ * </div>
13
+ */
14
+ declare function twoPane(node: HTMLElement, options?: TwoPaneOptions): {
15
+ update(next?: TwoPaneOptions): void;
16
+ destroy: () => void;
17
+ };
18
+ /** <div use:foldWhen={"tabletop"}>…</div> — hidden unless the posture matches. */
19
+ declare function foldWhen(node: HTMLElement, posture: Posture | Posture[]): {
20
+ update(next: Posture | Posture[]): void;
21
+ destroy: () => void;
22
+ };
23
+
24
+ export { fold, foldWhen, twoPane };
@@ -0,0 +1,24 @@
1
+ import { Readable } from 'svelte/store';
2
+ import { FoldState, Posture, TwoPaneOptions } from 'foldjs';
3
+ export { FoldState, Posture, Rect, Spanning, simulate } from 'foldjs';
4
+ export { mountDevtools } from 'foldjs/devtools';
5
+
6
+ /** Live foldable state: `$fold.posture`, `$fold.hinge`… */
7
+ declare const fold: Readable<FoldState>;
8
+ /**
9
+ * <div use:twoPane={{ fallback: "stack" }}>
10
+ * <div data-pane="primary">…</div>
11
+ * <div data-pane="secondary">…</div>
12
+ * </div>
13
+ */
14
+ declare function twoPane(node: HTMLElement, options?: TwoPaneOptions): {
15
+ update(next?: TwoPaneOptions): void;
16
+ destroy: () => void;
17
+ };
18
+ /** <div use:foldWhen={"tabletop"}>…</div> — hidden unless the posture matches. */
19
+ declare function foldWhen(node: HTMLElement, posture: Posture | Posture[]): {
20
+ update(next: Posture | Posture[]): void;
21
+ destroy: () => void;
22
+ };
23
+
24
+ export { fold, foldWhen, twoPane };
package/dist/index.js ADDED
@@ -0,0 +1,35 @@
1
+ // src/index.ts
2
+ import { readable } from "svelte/store";
3
+ import { bindTwoPane, getFold, subscribe } from "foldjs";
4
+ import { simulate } from "foldjs";
5
+ import { mountDevtools } from "foldjs/devtools";
6
+ var fold = readable(getFold(), (set) => {
7
+ set(getFold());
8
+ return subscribe(set);
9
+ });
10
+ function twoPane(node, options = {}) {
11
+ return bindTwoPane(node, options);
12
+ }
13
+ function foldWhen(node, posture) {
14
+ let wanted = posture;
15
+ const paint = () => {
16
+ const list = Array.isArray(wanted) ? wanted : [wanted];
17
+ node.hidden = !list.includes(getFold().posture);
18
+ };
19
+ const unsubscribe = subscribe(paint);
20
+ paint();
21
+ return {
22
+ update(next) {
23
+ wanted = next;
24
+ paint();
25
+ },
26
+ destroy: unsubscribe
27
+ };
28
+ }
29
+ export {
30
+ fold,
31
+ foldWhen,
32
+ mountDevtools,
33
+ simulate,
34
+ twoPane
35
+ };
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@foldjs/svelte",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "Svelte bindings for Fold.js: a `fold` store and `use:twoPane` / `use:foldWhen` actions.",
5
+ "license": "MIT",
6
+ "author": "christophe77",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/christophe77/foldjs.git",
10
+ "directory": "packages/svelte"
11
+ },
12
+ "homepage": "https://christophe77.github.io/foldjs/",
13
+ "bugs": "https://github.com/christophe77/foldjs/issues",
14
+ "type": "module",
15
+ "main": "./dist/index.cjs",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "svelte": "./dist/index.js",
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "sideEffects": false,
30
+ "keywords": [
31
+ "foldable",
32
+ "svelte",
33
+ "dual-screen",
34
+ "hinge",
35
+ "foldjs"
36
+ ],
37
+ "peerDependencies": {
38
+ "foldjs": "^0.1.0",
39
+ "svelte": ">=4"
40
+ },
41
+ "scripts": {
42
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean --external svelte --external foldjs",
43
+ "prepack": "node -e \"require('fs').copyFileSync('../../README.md','README.md')\""
44
+ }
45
+ }