@michaelyagi/shoji 0.1.0-alpha.6
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 +21 -0
- package/README.md +81 -0
- package/dist/esm/core/EventBus.d.ts +16 -0
- package/dist/esm/core/FocusTrap.d.ts +9 -0
- package/dist/esm/core/Gallery.d.ts +221 -0
- package/dist/esm/core/GestureController.d.ts +50 -0
- package/dist/esm/core/LiveRegion.d.ts +6 -0
- package/dist/esm/core/SlideManager.d.ts +83 -0
- package/dist/esm/core/bodyScrollLock.d.ts +2 -0
- package/dist/esm/core/dom.d.ts +27 -0
- package/dist/esm/core/icons.d.ts +6 -0
- package/dist/esm/core/index.d.ts +5 -0
- package/dist/esm/core/index.js +1966 -0
- package/dist/esm/core/index.js.map +1 -0
- package/dist/esm/core/plugin.d.ts +54 -0
- package/dist/esm/core/rotateFlipNormalize.d.ts +19 -0
- package/dist/esm/core/scan.d.ts +8 -0
- package/dist/esm/core/types.d.ts +268 -0
- package/dist/esm/core/zoomTransition.d.ts +33 -0
- package/dist/esm/gestures/GestureEngine.d.ts +78 -0
- package/dist/esm/index.css +475 -0
- package/dist/esm/index.d.ts +32 -0
- package/dist/esm/index.js +24 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index2.css +22 -0
- package/dist/esm/index3.css +166 -0
- package/dist/esm/index4.css +27 -0
- package/dist/esm/plugins/activeThumbnail/index.d.ts +26 -0
- package/dist/esm/plugins/activeThumbnail/index.js +48 -0
- package/dist/esm/plugins/activeThumbnail/index.js.map +1 -0
- package/dist/esm/plugins/autoplay/icons.d.ts +3 -0
- package/dist/esm/plugins/autoplay/index.d.ts +17 -0
- package/dist/esm/plugins/autoplay/index.js +177 -0
- package/dist/esm/plugins/autoplay/index.js.map +1 -0
- package/dist/esm/plugins/fullscreen/icons.d.ts +3 -0
- package/dist/esm/plugins/fullscreen/index.d.ts +17 -0
- package/dist/esm/plugins/fullscreen/index.js +74 -0
- package/dist/esm/plugins/fullscreen/index.js.map +1 -0
- package/dist/esm/plugins/layout/index.d.ts +191 -0
- package/dist/esm/plugins/layout/index.js +746 -0
- package/dist/esm/plugins/layout/index.js.map +1 -0
- package/dist/esm/plugins/layout/justified.d.ts +68 -0
- package/dist/esm/plugins/layout/masonry.d.ts +92 -0
- package/dist/esm/plugins/rotateFlip/icons.d.ts +5 -0
- package/dist/esm/plugins/rotateFlip/index.d.ts +17 -0
- package/dist/esm/plugins/rotateFlip/index.js +138 -0
- package/dist/esm/plugins/rotateFlip/index.js.map +1 -0
- package/dist/esm/plugins/video/index.d.ts +13 -0
- package/dist/esm/plugins/video/index.js +95 -0
- package/dist/esm/plugins/video/index.js.map +1 -0
- package/dist/esm/plugins/video/youtube.d.ts +61 -0
- package/dist/esm/plugins/zoom/icons.d.ts +4 -0
- package/dist/esm/plugins/zoom/index.d.ts +30 -0
- package/dist/esm/plugins/zoom/index.js +274 -0
- package/dist/esm/plugins/zoom/index.js.map +1 -0
- package/dist/esm/plugins/zoom/zoomMath.d.ts +24 -0
- package/dist/esm/transitions/SlideTransition.d.ts +25 -0
- package/dist/esm/transitions/presets.d.ts +21 -0
- package/dist/esm/zoomTransition-bbKHpVpA.js +110 -0
- package/dist/esm/zoomTransition-bbKHpVpA.js.map +1 -0
- package/dist/shoji.css +690 -0
- package/dist/shoji.js +3605 -0
- package/dist/shoji.js.map +1 -0
- package/dist/shoji.min.css +1 -0
- package/dist/shoji.min.js +2 -0
- package/dist/shoji.min.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { ShojiPlugin } from '../../core/plugin';
|
|
2
|
+
import { GalleryItem } from '../../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* DESIGN.md §5 — `type: 'grid' | 'masonry' | 'justified'`; masonry supports
|
|
5
|
+
* both `orientation`s, `breakpoints` (§5.4), and `groupBy`/headings (§5.2;
|
|
6
|
+
* see that option's own doc comment for the v1 scope cuts vs. the full
|
|
7
|
+
* spec, including why `groupBy` itself is excluded from `orientation:
|
|
8
|
+
* 'horizontal'`). Deliberately still
|
|
9
|
+
* deferred: jump-free *prepend* coordination (§5.2's scroll-anchoring
|
|
10
|
+
* handoff needs the not-yet-built scroll plugin on the other end —
|
|
11
|
+
* prepending today triggers a full relayout, which can shift scroll
|
|
12
|
+
* position if content above the fold grew).
|
|
13
|
+
*/
|
|
14
|
+
export interface LayoutOptions {
|
|
15
|
+
/** Default `'justified'`. */
|
|
16
|
+
type?: 'grid' | 'masonry' | 'justified';
|
|
17
|
+
gutter?: number | {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* `type: 'grid'` only — every cell's shape, cropped to fit via
|
|
23
|
+
* `object-fit: cover`; default 1 (square). Deliberately *not* each
|
|
24
|
+
* photo's own aspect ratio: plain CSS grid sizes a row's height to its
|
|
25
|
+
* tallest cell, so per-item ratios leave a visible blank gap under every
|
|
26
|
+
* shorter tile sharing a row with a taller one. Masonry/justified are
|
|
27
|
+
* the two types that preserve true per-photo aspect ratios instead (via
|
|
28
|
+
* their own JS packing, which doesn't have this row-height problem).
|
|
29
|
+
*/
|
|
30
|
+
aspectRatio?: number;
|
|
31
|
+
/**
|
|
32
|
+
* `type: 'masonry'` only. `'vertical'` (default): fixed-width columns,
|
|
33
|
+
* tiles stack top-to-bottom, ragged *bottom* edge. `'horizontal'`: fixed-
|
|
34
|
+
* height rows, tiles pack left-to-right, ragged *right* edge — the direct
|
|
35
|
+
* transpose. Both wrap/grow within the container and scroll vertically
|
|
36
|
+
* only, same as every other layout type; neither ever needs horizontal
|
|
37
|
+
* scroll. See `rowHeight` for `'horizontal'`'s one fixed input, and
|
|
38
|
+
* `justified` (a different `type` entirely) for the *opposite* tradeoff —
|
|
39
|
+
* width forced flush, height left to solve for.
|
|
40
|
+
*/
|
|
41
|
+
orientation?: 'vertical' | 'horizontal';
|
|
42
|
+
columns?: number | 'auto';
|
|
43
|
+
columnWidth?: number;
|
|
44
|
+
minColumnWidth?: number;
|
|
45
|
+
maxColumnWidth?: number;
|
|
46
|
+
fill?: 'shortest' | 'ordered';
|
|
47
|
+
/** `type: 'justified'`, or `type: 'masonry', orientation: 'horizontal'`. For horizontal masonry this is the row's exact, fixed height (see `orientation`'s doc comment) — `minRowHeight`/`maxRowHeight` don't apply there, since nothing is solved/clamped, only for justified, where it's a *target* a solved-for height converges near. */
|
|
48
|
+
rowHeight?: number;
|
|
49
|
+
minRowHeight?: number;
|
|
50
|
+
maxRowHeight?: number;
|
|
51
|
+
lastRow?: 'justify' | 'left' | 'hide';
|
|
52
|
+
animate?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Container-width → partial overrides, applied on top of the base options
|
|
55
|
+
* above whenever the container's current width is <= that key (the
|
|
56
|
+
* *narrowest* matching key wins if more than one applies). Re-evaluated on
|
|
57
|
+
* every relayout, so crossing a threshold while resizing takes effect
|
|
58
|
+
* live. Cannot override `type` or `orientation` — swapping the DOM
|
|
59
|
+
* structure/positioning strategy live is a bigger feature than a sizing
|
|
60
|
+
* tweak; use a media query + two `Shoji` instances if that's genuinely
|
|
61
|
+
* needed.
|
|
62
|
+
*/
|
|
63
|
+
breakpoints?: Record<number, Omit<LayoutOptions, 'type' | 'orientation' | 'breakpoints'>>;
|
|
64
|
+
/**
|
|
65
|
+
* Derives a section key per item (e.g. a formatted date) — a heading is
|
|
66
|
+
* inserted whenever the key changes between consecutive items, real
|
|
67
|
+
* "Today / Yesterday / March 2024" (Google Photos-style) sectioning.
|
|
68
|
+
* Items must already be grouped consecutively; a key reappearing later
|
|
69
|
+
* after a different key started a new section anyway.
|
|
70
|
+
*
|
|
71
|
+
* Section boundaries behave differently per `type`: `grid`'s heading is a
|
|
72
|
+
* full-span (`grid-column: 1 / -1`) element, native CSS grid gives it its
|
|
73
|
+
* own row for free. `masonry`'s heading is a full-width blocking element
|
|
74
|
+
* too — each section is its own fresh column-packing pass, no two
|
|
75
|
+
* sections ever share visual space. `justified` is the odd one out, by
|
|
76
|
+
* design (this is the actual Google Photos behavior, not a simplified
|
|
77
|
+
* approximation of it): sections do **not** force a row break. Row
|
|
78
|
+
* *composition* ignores section boundaries entirely — one continuous
|
|
79
|
+
* `layoutJustified` pass packs every item regardless of section, so a
|
|
80
|
+
* section with too few items to reach a full row's target width (a
|
|
81
|
+
* single lone photo, say) shares that row with whatever comes right
|
|
82
|
+
* after it, instead of getting stretched into its own awkward
|
|
83
|
+
* almost-empty row. A heading only marks *where* a new section starts:
|
|
84
|
+
* a compact, inline label sized to its own content (not full width),
|
|
85
|
+
* positioned at the x-coordinate of the tile that starts its section,
|
|
86
|
+
* in a slim label-band above whichever row that tile landed on — more
|
|
87
|
+
* than one label can share the same band if more than one section
|
|
88
|
+
* happens to start within the same row (see `renderHeading`'s
|
|
89
|
+
* `{title, subtitle}` form for exactly this — that's what the reference
|
|
90
|
+
* behavior actually looks like).
|
|
91
|
+
*
|
|
92
|
+
* v1 scope cuts vs. DESIGN.md §5.2's full spec: (1) any items change
|
|
93
|
+
* while `groupBy` is set does a full relayout, same simplification
|
|
94
|
+
* justified's non-grouped path already makes for appends (§5.4) — the
|
|
95
|
+
* "merge across load boundaries" incremental optimization is deferred;
|
|
96
|
+
* (2) headings are always `<h2>`, not a configurable level; (3) not
|
|
97
|
+
* supported with `orientation: 'horizontal'` (warns, ignored) —
|
|
98
|
+
* DESIGN.md itself calls that pairing rare.
|
|
99
|
+
*/
|
|
100
|
+
groupBy?: (item: GalleryItem) => string;
|
|
101
|
+
/**
|
|
102
|
+
* Customizes a heading's content; default renders the key as plain text.
|
|
103
|
+
* Three return shapes:
|
|
104
|
+
* - `string` — plain text (default behavior, just with custom content).
|
|
105
|
+
* - `HTMLElement` — full control, own tag/children; the plugin adds its
|
|
106
|
+
* own class/positioning on top of whatever's returned, nothing else.
|
|
107
|
+
* - `{ title: string; subtitle?: string }` — the built-in structured
|
|
108
|
+
* form (bold title + a smaller, muted `subtitle`, e.g. a date + a
|
|
109
|
+
* location) — the only form the plugin can apply automatic overflow
|
|
110
|
+
* handling to (see `headingOverflow`), since it owns the DOM structure
|
|
111
|
+
* (a raw `HTMLElement` is opaque to it, no safe way to guess what's
|
|
112
|
+
* droppable).
|
|
113
|
+
*/
|
|
114
|
+
renderHeading?: (key: string, items: GalleryItem[]) => string | HTMLElement | {
|
|
115
|
+
title: string;
|
|
116
|
+
subtitle?: string;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* `type: 'justified'` + the `{ title, subtitle }` structured heading
|
|
120
|
+
* form only — controls what happens when a compact label doesn't fit
|
|
121
|
+
* its available width (the gap until the next section's label sharing
|
|
122
|
+
* its row, or the container edge). Ignored otherwise: `grid`/`masonry`
|
|
123
|
+
* headings are full-width and this kind of squeeze can't happen there;
|
|
124
|
+
* a raw `renderHeading`-returned `HTMLElement`/`string` is left exactly
|
|
125
|
+
* as returned regardless, since the plugin has no safe way to guess
|
|
126
|
+
* what's droppable in an opaque element.
|
|
127
|
+
* - `'show'` (default) — always render the full title + subtitle, one
|
|
128
|
+
* line, however wide; a label can visually run past the next
|
|
129
|
+
* section's label or the container edge if the content is long
|
|
130
|
+
* enough. The simple, predictable default — nothing gets silently
|
|
131
|
+
* dropped or reflowed.
|
|
132
|
+
* - `'fit'` — never wraps a label's text. First the subtitle is dropped
|
|
133
|
+
* if title+subtitle together don't fit; if the title *alone* still
|
|
134
|
+
* doesn't fit next to whatever's sharing its row, that section is
|
|
135
|
+
* pushed to start a fresh row instead, giving its label the room it
|
|
136
|
+
* needs — row *composition* responds to label width, not just label
|
|
137
|
+
* content. Real Google Photos behavior; opt in when labels regularly
|
|
138
|
+
* need to share tight row space. The one unavoidable exception is a
|
|
139
|
+
* single label wider than the entire container even alone on its own
|
|
140
|
+
* row — there, nothing left to break onto, so the label is
|
|
141
|
+
* ellipsis-truncated (still one line, never wrapped, never
|
|
142
|
+
* overflowing).
|
|
143
|
+
* - `'wrap'` — the in-between: same continuous row-packing as `'show'`
|
|
144
|
+
* (row *composition* never reacts to label width, unlike `'fit'` — no
|
|
145
|
+
* section is ever pushed to a fresh row), but a label that doesn't fit
|
|
146
|
+
* its available width (same gap `'fit'` measures) wraps its own text
|
|
147
|
+
* onto additional lines instead of running past it. Height is capped
|
|
148
|
+
* at `maxRowHeight` (or its default, 360) — a label tall enough to hit
|
|
149
|
+
* that cap ellipsis-truncates its last visible line rather than
|
|
150
|
+
* growing the row further. Real Google Photos behavior for its date
|
|
151
|
+
* headers; pick this over `'fit'` when you'd rather a label take an
|
|
152
|
+
* extra line than shove a whole section onto its own row.
|
|
153
|
+
*/
|
|
154
|
+
headingOverflow?: 'show' | 'fit' | 'wrap';
|
|
155
|
+
/**
|
|
156
|
+
* Pins the active section's heading via `position: sticky`. Only
|
|
157
|
+
* implemented for `type: 'grid'`, where headings sit in normal document
|
|
158
|
+
* flow — masonry/justified headings are absolutely positioned by JS (like
|
|
159
|
+
* their tiles), and `position: sticky` doesn't do anything meaningful
|
|
160
|
+
* layered onto an already explicitly-positioned element. Warns and is
|
|
161
|
+
* ignored for those two types.
|
|
162
|
+
*/
|
|
163
|
+
stickyHeadings?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* When an item is missing `width`/`height`, measure its tile's own `<img>`
|
|
166
|
+
* once it loads (`naturalWidth`/`naturalHeight`) and correct that tile's
|
|
167
|
+
* aspect ratio in place, rather than leaving it at the permanent 4:3
|
|
168
|
+
* placeholder fallback. Default `true`.
|
|
169
|
+
*
|
|
170
|
+
* The *first* layout pass never waits on this — it always uses the 4:3
|
|
171
|
+
* placeholder immediately, same as before this option existed, so opening
|
|
172
|
+
* the gallery is never blocked on image loads (DESIGN.md §5.2's
|
|
173
|
+
* never-measure-mid-layout-pass rule still holds for that first pass).
|
|
174
|
+
* This only ever *corrects* a placeholder after the fact, once a real
|
|
175
|
+
* measurement lands — the same "async correction after an initial
|
|
176
|
+
* synchronous pass" pattern already used for a `containerWidth <= 0`
|
|
177
|
+
* container (§5.4) and the zoom transition's origin-rect race (§2.3b),
|
|
178
|
+
* extended to per-item dimensions. Multiple corrections landing close
|
|
179
|
+
* together (e.g. several cached images resolving in the same tick) are
|
|
180
|
+
* coalesced into one relayout via `requestAnimationFrame`, not one
|
|
181
|
+
* relayout per image.
|
|
182
|
+
*
|
|
183
|
+
* Effectively does automatically, for `thumb`/`poster`/`src`, what a host
|
|
184
|
+
* would otherwise have to do by hand before constructing the gallery
|
|
185
|
+
* (`new Image(); img.onload = () => ...`) — set `false` to keep the old
|
|
186
|
+
* behavior (permanent 4:3 fallback, no self-correction) if you'd rather
|
|
187
|
+
* guarantee zero extra relayouts under any circumstance.
|
|
188
|
+
*/
|
|
189
|
+
autoMeasure?: boolean;
|
|
190
|
+
}
|
|
191
|
+
export declare const Layout: ShojiPlugin;
|