concertina 0.6.1 → 0.7.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/index.cjs +97 -8
- package/dist/index.d.cts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +99 -8
- package/dist/styles.css +48 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,12 +33,15 @@ __export(index_exports, {
|
|
|
33
33
|
ConcertinaContext: () => ConcertinaContext,
|
|
34
34
|
ConcertinaStore: () => ConcertinaStore,
|
|
35
35
|
Content: () => Content3,
|
|
36
|
+
Gigbag: () => Gigbag,
|
|
37
|
+
Glide: () => Glide,
|
|
36
38
|
Header: () => Header,
|
|
37
39
|
Item: () => Item2,
|
|
38
40
|
Root: () => Root3,
|
|
39
41
|
Slot: () => Slot,
|
|
40
42
|
StableSlot: () => StableSlot,
|
|
41
43
|
Trigger: () => Trigger2,
|
|
44
|
+
Warmup: () => Warmup,
|
|
42
45
|
pinToScrollTop: () => pinToScrollTop,
|
|
43
46
|
useConcertina: () => useConcertina,
|
|
44
47
|
useExpanded: () => useExpanded,
|
|
@@ -1255,13 +1258,96 @@ function useStableSlot(options = {}) {
|
|
|
1255
1258
|
return { ref, style };
|
|
1256
1259
|
}
|
|
1257
1260
|
|
|
1258
|
-
// src/
|
|
1261
|
+
// src/gigbag.tsx
|
|
1259
1262
|
var import_react13 = require("react");
|
|
1263
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1264
|
+
var Gigbag = (0, import_react13.forwardRef)(
|
|
1265
|
+
function Gigbag2({ axis = "height", as: Tag = "div", className, style, children, ...props }, fwdRef) {
|
|
1266
|
+
const { ref: ratchetRef, style: ratchetStyle } = useStableSlot({ axis });
|
|
1267
|
+
const merged = className ? `concertina-gigbag ${className}` : "concertina-gigbag";
|
|
1268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1269
|
+
Tag,
|
|
1270
|
+
{
|
|
1271
|
+
ref: (el) => {
|
|
1272
|
+
ratchetRef(el);
|
|
1273
|
+
if (typeof fwdRef === "function") fwdRef(el);
|
|
1274
|
+
else if (fwdRef) fwdRef.current = el;
|
|
1275
|
+
},
|
|
1276
|
+
className: merged,
|
|
1277
|
+
style: { ...ratchetStyle, ...style },
|
|
1278
|
+
...props,
|
|
1279
|
+
children
|
|
1280
|
+
}
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
);
|
|
1284
|
+
|
|
1285
|
+
// src/warmup.tsx
|
|
1286
|
+
var import_react14 = require("react");
|
|
1287
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1288
|
+
var Warmup = (0, import_react14.forwardRef)(
|
|
1289
|
+
function Warmup2({ rows = 3, columns = 1, as: Tag = "div", className, children, ...props }, ref) {
|
|
1290
|
+
const merged = className ? `concertina-warmup ${className}` : "concertina-warmup";
|
|
1291
|
+
const cells = Array.from({ length: rows * columns }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "concertina-warmup-bone" }, i));
|
|
1292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1293
|
+
Tag,
|
|
1294
|
+
{
|
|
1295
|
+
ref,
|
|
1296
|
+
className: merged,
|
|
1297
|
+
style: { gridTemplateColumns: `repeat(${columns}, 1fr)` },
|
|
1298
|
+
...props,
|
|
1299
|
+
children: cells
|
|
1300
|
+
}
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
);
|
|
1304
|
+
|
|
1305
|
+
// src/glide.tsx
|
|
1306
|
+
var import_react15 = require("react");
|
|
1307
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1308
|
+
var Glide = (0, import_react15.forwardRef)(
|
|
1309
|
+
function Glide2({ show, as: Tag = "div", className, children, ...props }, ref) {
|
|
1310
|
+
const [mounted, setMounted] = (0, import_react15.useState)(show);
|
|
1311
|
+
const [phase, setPhase] = (0, import_react15.useState)(show ? "entered" : "exiting");
|
|
1312
|
+
(0, import_react15.useEffect)(() => {
|
|
1313
|
+
if (show) {
|
|
1314
|
+
setMounted(true);
|
|
1315
|
+
setPhase("entering");
|
|
1316
|
+
} else if (mounted) {
|
|
1317
|
+
setPhase("exiting");
|
|
1318
|
+
}
|
|
1319
|
+
}, [show]);
|
|
1320
|
+
const onAnimationEnd = (0, import_react15.useCallback)(
|
|
1321
|
+
(e) => {
|
|
1322
|
+
if (e.target !== e.currentTarget) return;
|
|
1323
|
+
if (phase === "entering") setPhase("entered");
|
|
1324
|
+
if (phase === "exiting") setMounted(false);
|
|
1325
|
+
},
|
|
1326
|
+
[phase]
|
|
1327
|
+
);
|
|
1328
|
+
if (!mounted) return null;
|
|
1329
|
+
const phaseClass = phase === "entering" ? "concertina-glide-entering" : phase === "exiting" ? "concertina-glide-exiting" : "";
|
|
1330
|
+
const merged = ["concertina-glide", phaseClass, className].filter(Boolean).join(" ");
|
|
1331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1332
|
+
Tag,
|
|
1333
|
+
{
|
|
1334
|
+
ref,
|
|
1335
|
+
className: merged,
|
|
1336
|
+
onAnimationEnd,
|
|
1337
|
+
...props,
|
|
1338
|
+
children
|
|
1339
|
+
}
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
);
|
|
1343
|
+
|
|
1344
|
+
// src/use-concertina.ts
|
|
1345
|
+
var import_react16 = require("react");
|
|
1260
1346
|
function useConcertina() {
|
|
1261
|
-
const [value, setValue] = (0,
|
|
1262
|
-
const [switching, setSwitching] = (0,
|
|
1263
|
-
const itemRefs = (0,
|
|
1264
|
-
const onValueChange = (0,
|
|
1347
|
+
const [value, setValue] = (0, import_react16.useState)("");
|
|
1348
|
+
const [switching, setSwitching] = (0, import_react16.useState)(false);
|
|
1349
|
+
const itemRefs = (0, import_react16.useRef)({});
|
|
1350
|
+
const onValueChange = (0, import_react16.useCallback)(
|
|
1265
1351
|
(newValue) => {
|
|
1266
1352
|
if (!newValue) {
|
|
1267
1353
|
setSwitching(false);
|
|
@@ -1273,14 +1359,14 @@ function useConcertina() {
|
|
|
1273
1359
|
},
|
|
1274
1360
|
[value]
|
|
1275
1361
|
);
|
|
1276
|
-
(0,
|
|
1362
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
1277
1363
|
if (!value) return;
|
|
1278
1364
|
pinToScrollTop(itemRefs.current[value]);
|
|
1279
1365
|
}, [value]);
|
|
1280
|
-
(0,
|
|
1366
|
+
(0, import_react16.useEffect)(() => {
|
|
1281
1367
|
if (switching) setSwitching(false);
|
|
1282
1368
|
}, [switching]);
|
|
1283
|
-
const getItemRef = (0,
|
|
1369
|
+
const getItemRef = (0, import_react16.useCallback)(
|
|
1284
1370
|
(id) => (el) => {
|
|
1285
1371
|
itemRefs.current[id] = el;
|
|
1286
1372
|
},
|
|
@@ -1298,12 +1384,15 @@ function useConcertina() {
|
|
|
1298
1384
|
ConcertinaContext,
|
|
1299
1385
|
ConcertinaStore,
|
|
1300
1386
|
Content,
|
|
1387
|
+
Gigbag,
|
|
1388
|
+
Glide,
|
|
1301
1389
|
Header,
|
|
1302
1390
|
Item,
|
|
1303
1391
|
Root,
|
|
1304
1392
|
Slot,
|
|
1305
1393
|
StableSlot,
|
|
1306
1394
|
Trigger,
|
|
1395
|
+
Warmup,
|
|
1307
1396
|
pinToScrollTop,
|
|
1308
1397
|
useConcertina,
|
|
1309
1398
|
useExpanded,
|
package/dist/index.d.cts
CHANGED
|
@@ -115,6 +115,60 @@ declare function useTransitionLock(): {
|
|
|
115
115
|
readonly lock: () => void;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
interface GigbagProps extends HTMLAttributes<HTMLElement> {
|
|
119
|
+
/** Which axis to ratchet. Default: "height". */
|
|
120
|
+
axis?: Axis;
|
|
121
|
+
/** HTML element to render. Default: "div". */
|
|
122
|
+
as?: ElementType;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Size-reserving container.
|
|
126
|
+
*
|
|
127
|
+
* Remembers its largest-ever size (ResizeObserver ratchet) and never
|
|
128
|
+
* shrinks. Swap a spinner for a table inside — no reflow.
|
|
129
|
+
*
|
|
130
|
+
* Uses `contain: layout style` to isolate internal reflow from
|
|
131
|
+
* ancestors.
|
|
132
|
+
*/
|
|
133
|
+
declare const Gigbag: react.ForwardRefExoticComponent<GigbagProps & react.RefAttributes<HTMLElement>>;
|
|
134
|
+
|
|
135
|
+
interface WarmupProps extends HTMLAttributes<HTMLElement> {
|
|
136
|
+
/** Number of placeholder rows. Default: 3. */
|
|
137
|
+
rows?: number;
|
|
138
|
+
/** Number of columns per row. Default: 1. */
|
|
139
|
+
columns?: number;
|
|
140
|
+
/** HTML element to render. Default: "div". */
|
|
141
|
+
as?: ElementType;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Structural placeholder — CSS-only shimmer grid.
|
|
145
|
+
*
|
|
146
|
+
* Renders `rows x columns` animated bones that approximate the
|
|
147
|
+
* dimensions of the real content. Pair with <Gigbag> so the
|
|
148
|
+
* container ratchets to the larger of placeholder vs real content.
|
|
149
|
+
*
|
|
150
|
+
* All dimensions are CSS custom properties — consuming apps theme
|
|
151
|
+
* without forking.
|
|
152
|
+
*/
|
|
153
|
+
declare const Warmup: react.ForwardRefExoticComponent<WarmupProps & react.RefAttributes<HTMLElement>>;
|
|
154
|
+
|
|
155
|
+
interface GlideProps extends HTMLAttributes<HTMLElement> {
|
|
156
|
+
/** Whether the content is visible. */
|
|
157
|
+
show: boolean;
|
|
158
|
+
/** HTML element to render. Default: "div". */
|
|
159
|
+
as?: ElementType;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Enter/exit animation wrapper.
|
|
163
|
+
*
|
|
164
|
+
* State machine:
|
|
165
|
+
* show=true -> mount + "entering" -> animationEnd -> "entered"
|
|
166
|
+
* show=false -> "exiting" -> animationEnd -> unmount
|
|
167
|
+
*
|
|
168
|
+
* CSS classes: concertina-glide-entering, concertina-glide-exiting
|
|
169
|
+
*/
|
|
170
|
+
declare const Glide: react.ForwardRefExoticComponent<GlideProps & react.RefAttributes<HTMLElement>>;
|
|
171
|
+
|
|
118
172
|
/**
|
|
119
173
|
* Scroll `el` to the top of its nearest scrollable ancestor,
|
|
120
174
|
* clearing any sticky headers. Only adjusts one container's
|
|
@@ -157,4 +211,4 @@ interface UseConcertinaReturn {
|
|
|
157
211
|
*/
|
|
158
212
|
declare function useConcertina(): UseConcertinaReturn;
|
|
159
213
|
|
|
160
|
-
export { type Axis, ConcertinaContext, type ConcertinaRootProps, ConcertinaStore, Content, Item, Root, Slot, type SlotProps, StableSlot, type StableSlotProps, type UseConcertinaReturn, pinToScrollTop, useConcertina, useExpanded, useStableSlot, useTransitionLock };
|
|
214
|
+
export { type Axis, ConcertinaContext, type ConcertinaRootProps, ConcertinaStore, Content, Gigbag, type GigbagProps, Glide, type GlideProps, Item, Root, Slot, type SlotProps, StableSlot, type StableSlotProps, type UseConcertinaReturn, Warmup, type WarmupProps, pinToScrollTop, useConcertina, useExpanded, useStableSlot, useTransitionLock };
|
package/dist/index.d.ts
CHANGED
|
@@ -115,6 +115,60 @@ declare function useTransitionLock(): {
|
|
|
115
115
|
readonly lock: () => void;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
interface GigbagProps extends HTMLAttributes<HTMLElement> {
|
|
119
|
+
/** Which axis to ratchet. Default: "height". */
|
|
120
|
+
axis?: Axis;
|
|
121
|
+
/** HTML element to render. Default: "div". */
|
|
122
|
+
as?: ElementType;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Size-reserving container.
|
|
126
|
+
*
|
|
127
|
+
* Remembers its largest-ever size (ResizeObserver ratchet) and never
|
|
128
|
+
* shrinks. Swap a spinner for a table inside — no reflow.
|
|
129
|
+
*
|
|
130
|
+
* Uses `contain: layout style` to isolate internal reflow from
|
|
131
|
+
* ancestors.
|
|
132
|
+
*/
|
|
133
|
+
declare const Gigbag: react.ForwardRefExoticComponent<GigbagProps & react.RefAttributes<HTMLElement>>;
|
|
134
|
+
|
|
135
|
+
interface WarmupProps extends HTMLAttributes<HTMLElement> {
|
|
136
|
+
/** Number of placeholder rows. Default: 3. */
|
|
137
|
+
rows?: number;
|
|
138
|
+
/** Number of columns per row. Default: 1. */
|
|
139
|
+
columns?: number;
|
|
140
|
+
/** HTML element to render. Default: "div". */
|
|
141
|
+
as?: ElementType;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Structural placeholder — CSS-only shimmer grid.
|
|
145
|
+
*
|
|
146
|
+
* Renders `rows x columns` animated bones that approximate the
|
|
147
|
+
* dimensions of the real content. Pair with <Gigbag> so the
|
|
148
|
+
* container ratchets to the larger of placeholder vs real content.
|
|
149
|
+
*
|
|
150
|
+
* All dimensions are CSS custom properties — consuming apps theme
|
|
151
|
+
* without forking.
|
|
152
|
+
*/
|
|
153
|
+
declare const Warmup: react.ForwardRefExoticComponent<WarmupProps & react.RefAttributes<HTMLElement>>;
|
|
154
|
+
|
|
155
|
+
interface GlideProps extends HTMLAttributes<HTMLElement> {
|
|
156
|
+
/** Whether the content is visible. */
|
|
157
|
+
show: boolean;
|
|
158
|
+
/** HTML element to render. Default: "div". */
|
|
159
|
+
as?: ElementType;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Enter/exit animation wrapper.
|
|
163
|
+
*
|
|
164
|
+
* State machine:
|
|
165
|
+
* show=true -> mount + "entering" -> animationEnd -> "entered"
|
|
166
|
+
* show=false -> "exiting" -> animationEnd -> unmount
|
|
167
|
+
*
|
|
168
|
+
* CSS classes: concertina-glide-entering, concertina-glide-exiting
|
|
169
|
+
*/
|
|
170
|
+
declare const Glide: react.ForwardRefExoticComponent<GlideProps & react.RefAttributes<HTMLElement>>;
|
|
171
|
+
|
|
118
172
|
/**
|
|
119
173
|
* Scroll `el` to the top of its nearest scrollable ancestor,
|
|
120
174
|
* clearing any sticky headers. Only adjusts one container's
|
|
@@ -157,4 +211,4 @@ interface UseConcertinaReturn {
|
|
|
157
211
|
*/
|
|
158
212
|
declare function useConcertina(): UseConcertinaReturn;
|
|
159
213
|
|
|
160
|
-
export { type Axis, ConcertinaContext, type ConcertinaRootProps, ConcertinaStore, Content, Item, Root, Slot, type SlotProps, StableSlot, type StableSlotProps, type UseConcertinaReturn, pinToScrollTop, useConcertina, useExpanded, useStableSlot, useTransitionLock };
|
|
214
|
+
export { type Axis, ConcertinaContext, type ConcertinaRootProps, ConcertinaStore, Content, Gigbag, type GigbagProps, Glide, type GlideProps, Item, Root, Slot, type SlotProps, StableSlot, type StableSlotProps, type UseConcertinaReturn, Warmup, type WarmupProps, pinToScrollTop, useConcertina, useExpanded, useStableSlot, useTransitionLock };
|
package/dist/index.js
CHANGED
|
@@ -1222,19 +1222,107 @@ function useStableSlot(options = {}) {
|
|
|
1222
1222
|
return { ref, style };
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
|
-
// src/
|
|
1225
|
+
// src/gigbag.tsx
|
|
1226
|
+
import { forwardRef as forwardRef9 } from "react";
|
|
1227
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1228
|
+
var Gigbag = forwardRef9(
|
|
1229
|
+
function Gigbag2({ axis = "height", as: Tag = "div", className, style, children, ...props }, fwdRef) {
|
|
1230
|
+
const { ref: ratchetRef, style: ratchetStyle } = useStableSlot({ axis });
|
|
1231
|
+
const merged = className ? `concertina-gigbag ${className}` : "concertina-gigbag";
|
|
1232
|
+
return /* @__PURE__ */ jsx13(
|
|
1233
|
+
Tag,
|
|
1234
|
+
{
|
|
1235
|
+
ref: (el) => {
|
|
1236
|
+
ratchetRef(el);
|
|
1237
|
+
if (typeof fwdRef === "function") fwdRef(el);
|
|
1238
|
+
else if (fwdRef) fwdRef.current = el;
|
|
1239
|
+
},
|
|
1240
|
+
className: merged,
|
|
1241
|
+
style: { ...ratchetStyle, ...style },
|
|
1242
|
+
...props,
|
|
1243
|
+
children
|
|
1244
|
+
}
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
);
|
|
1248
|
+
|
|
1249
|
+
// src/warmup.tsx
|
|
1250
|
+
import { forwardRef as forwardRef10 } from "react";
|
|
1251
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1252
|
+
var Warmup = forwardRef10(
|
|
1253
|
+
function Warmup2({ rows = 3, columns = 1, as: Tag = "div", className, children, ...props }, ref) {
|
|
1254
|
+
const merged = className ? `concertina-warmup ${className}` : "concertina-warmup";
|
|
1255
|
+
const cells = Array.from({ length: rows * columns }, (_, i) => /* @__PURE__ */ jsx14("div", { className: "concertina-warmup-bone" }, i));
|
|
1256
|
+
return /* @__PURE__ */ jsx14(
|
|
1257
|
+
Tag,
|
|
1258
|
+
{
|
|
1259
|
+
ref,
|
|
1260
|
+
className: merged,
|
|
1261
|
+
style: { gridTemplateColumns: `repeat(${columns}, 1fr)` },
|
|
1262
|
+
...props,
|
|
1263
|
+
children: cells
|
|
1264
|
+
}
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
);
|
|
1268
|
+
|
|
1269
|
+
// src/glide.tsx
|
|
1226
1270
|
import {
|
|
1271
|
+
forwardRef as forwardRef11,
|
|
1227
1272
|
useState as useState7,
|
|
1228
|
-
|
|
1273
|
+
useEffect as useEffect6,
|
|
1274
|
+
useCallback as useCallback9
|
|
1275
|
+
} from "react";
|
|
1276
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1277
|
+
var Glide = forwardRef11(
|
|
1278
|
+
function Glide2({ show, as: Tag = "div", className, children, ...props }, ref) {
|
|
1279
|
+
const [mounted, setMounted] = useState7(show);
|
|
1280
|
+
const [phase, setPhase] = useState7(show ? "entered" : "exiting");
|
|
1281
|
+
useEffect6(() => {
|
|
1282
|
+
if (show) {
|
|
1283
|
+
setMounted(true);
|
|
1284
|
+
setPhase("entering");
|
|
1285
|
+
} else if (mounted) {
|
|
1286
|
+
setPhase("exiting");
|
|
1287
|
+
}
|
|
1288
|
+
}, [show]);
|
|
1289
|
+
const onAnimationEnd = useCallback9(
|
|
1290
|
+
(e) => {
|
|
1291
|
+
if (e.target !== e.currentTarget) return;
|
|
1292
|
+
if (phase === "entering") setPhase("entered");
|
|
1293
|
+
if (phase === "exiting") setMounted(false);
|
|
1294
|
+
},
|
|
1295
|
+
[phase]
|
|
1296
|
+
);
|
|
1297
|
+
if (!mounted) return null;
|
|
1298
|
+
const phaseClass = phase === "entering" ? "concertina-glide-entering" : phase === "exiting" ? "concertina-glide-exiting" : "";
|
|
1299
|
+
const merged = ["concertina-glide", phaseClass, className].filter(Boolean).join(" ");
|
|
1300
|
+
return /* @__PURE__ */ jsx15(
|
|
1301
|
+
Tag,
|
|
1302
|
+
{
|
|
1303
|
+
ref,
|
|
1304
|
+
className: merged,
|
|
1305
|
+
onAnimationEnd,
|
|
1306
|
+
...props,
|
|
1307
|
+
children
|
|
1308
|
+
}
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
);
|
|
1312
|
+
|
|
1313
|
+
// src/use-concertina.ts
|
|
1314
|
+
import {
|
|
1315
|
+
useState as useState8,
|
|
1316
|
+
useCallback as useCallback10,
|
|
1229
1317
|
useRef as useRef7,
|
|
1230
1318
|
useLayoutEffect as useLayoutEffect4,
|
|
1231
|
-
useEffect as
|
|
1319
|
+
useEffect as useEffect7
|
|
1232
1320
|
} from "react";
|
|
1233
1321
|
function useConcertina() {
|
|
1234
|
-
const [value, setValue] =
|
|
1235
|
-
const [switching, setSwitching] =
|
|
1322
|
+
const [value, setValue] = useState8("");
|
|
1323
|
+
const [switching, setSwitching] = useState8(false);
|
|
1236
1324
|
const itemRefs = useRef7({});
|
|
1237
|
-
const onValueChange =
|
|
1325
|
+
const onValueChange = useCallback10(
|
|
1238
1326
|
(newValue) => {
|
|
1239
1327
|
if (!newValue) {
|
|
1240
1328
|
setSwitching(false);
|
|
@@ -1250,10 +1338,10 @@ function useConcertina() {
|
|
|
1250
1338
|
if (!value) return;
|
|
1251
1339
|
pinToScrollTop(itemRefs.current[value]);
|
|
1252
1340
|
}, [value]);
|
|
1253
|
-
|
|
1341
|
+
useEffect7(() => {
|
|
1254
1342
|
if (switching) setSwitching(false);
|
|
1255
1343
|
}, [switching]);
|
|
1256
|
-
const getItemRef =
|
|
1344
|
+
const getItemRef = useCallback10(
|
|
1257
1345
|
(id) => (el) => {
|
|
1258
1346
|
itemRefs.current[id] = el;
|
|
1259
1347
|
},
|
|
@@ -1270,12 +1358,15 @@ export {
|
|
|
1270
1358
|
ConcertinaContext,
|
|
1271
1359
|
ConcertinaStore,
|
|
1272
1360
|
Content3 as Content,
|
|
1361
|
+
Gigbag,
|
|
1362
|
+
Glide,
|
|
1273
1363
|
Header,
|
|
1274
1364
|
Item2 as Item,
|
|
1275
1365
|
Root3 as Root,
|
|
1276
1366
|
Slot,
|
|
1277
1367
|
StableSlot,
|
|
1278
1368
|
Trigger2 as Trigger,
|
|
1369
|
+
Warmup,
|
|
1279
1370
|
pinToScrollTop,
|
|
1280
1371
|
useConcertina,
|
|
1281
1372
|
useExpanded,
|
package/dist/styles.css
CHANGED
|
@@ -65,3 +65,51 @@
|
|
|
65
65
|
display: flex;
|
|
66
66
|
flex-direction: column;
|
|
67
67
|
}
|
|
68
|
+
|
|
69
|
+
/* Gigbag — size-reserving container.
|
|
70
|
+
contain isolates internal reflow from ancestors. */
|
|
71
|
+
.concertina-gigbag {
|
|
72
|
+
contain: layout style;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Warmup — structural placeholder shimmer grid. */
|
|
76
|
+
.concertina-warmup {
|
|
77
|
+
display: grid;
|
|
78
|
+
gap: var(--concertina-warmup-gap, 0.75rem);
|
|
79
|
+
contain: layout style;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.concertina-warmup-bone {
|
|
83
|
+
height: var(--concertina-warmup-bone-height, 1rem);
|
|
84
|
+
border-radius: var(--concertina-warmup-bone-radius, 0.25rem);
|
|
85
|
+
background: var(--concertina-warmup-bone-color, #e5e7eb);
|
|
86
|
+
animation: concertina-shimmer 1.5s ease-in-out infinite;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@keyframes concertina-shimmer {
|
|
90
|
+
0%, 100% { opacity: 1; }
|
|
91
|
+
50% { opacity: 0.4; }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Glide — enter/exit animation wrapper. */
|
|
95
|
+
.concertina-glide {
|
|
96
|
+
--concertina-glide-duration: 200ms;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.concertina-glide-entering {
|
|
100
|
+
animation: concertina-glide-in var(--concertina-glide-duration) ease-out;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.concertina-glide-exiting {
|
|
104
|
+
animation: concertina-glide-out var(--concertina-glide-duration) ease-out forwards;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@keyframes concertina-glide-in {
|
|
108
|
+
from { opacity: 0; max-height: 0; overflow: hidden; }
|
|
109
|
+
to { opacity: 1; max-height: var(--concertina-glide-height, 1000px); overflow: hidden; }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@keyframes concertina-glide-out {
|
|
113
|
+
from { opacity: 1; max-height: var(--concertina-glide-height, 1000px); overflow: hidden; }
|
|
114
|
+
to { opacity: 0; max-height: 0; overflow: hidden; }
|
|
115
|
+
}
|