@flight-framework/transitions 0.1.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/README.md +232 -0
- package/dist/adapters/react/index.d.ts +210 -0
- package/dist/adapters/react/index.js +261 -0
- package/dist/adapters/react/index.js.map +1 -0
- package/dist/adapters/solid/index.d.ts +5 -0
- package/dist/adapters/solid/index.js +9 -0
- package/dist/adapters/solid/index.js.map +1 -0
- package/dist/adapters/svelte/index.d.ts +5 -0
- package/dist/adapters/svelte/index.js +9 -0
- package/dist/adapters/svelte/index.js.map +1 -0
- package/dist/adapters/vue/index.d.ts +5 -0
- package/dist/adapters/vue/index.js +9 -0
- package/dist/adapters/vue/index.js.map +1 -0
- package/dist/chunk-4SF4GHDQ.js +252 -0
- package/dist/chunk-4SF4GHDQ.js.map +1 -0
- package/dist/chunk-7R3FXL3A.js +442 -0
- package/dist/chunk-7R3FXL3A.js.map +1 -0
- package/dist/chunk-BAILQEFB.js +136 -0
- package/dist/chunk-BAILQEFB.js.map +1 -0
- package/dist/chunk-ITLC6KJ4.js +138 -0
- package/dist/chunk-ITLC6KJ4.js.map +1 -0
- package/dist/chunk-JRRJMJDL.js +121 -0
- package/dist/chunk-JRRJMJDL.js.map +1 -0
- package/dist/chunk-UZUZC3MA.js +190 -0
- package/dist/chunk-UZUZC3MA.js.map +1 -0
- package/dist/chunk-W7HSR35B.js +3 -0
- package/dist/chunk-W7HSR35B.js.map +1 -0
- package/dist/chunk-WDXXYC7B.js +70 -0
- package/dist/chunk-WDXXYC7B.js.map +1 -0
- package/dist/chunk-XLVYHPII.js +3 -0
- package/dist/chunk-XLVYHPII.js.map +1 -0
- package/dist/chunk-ZBJ6FSAK.js +438 -0
- package/dist/chunk-ZBJ6FSAK.js.map +1 -0
- package/dist/component/index.d.ts +87 -0
- package/dist/component/index.js +5 -0
- package/dist/component/index.js.map +1 -0
- package/dist/config/index.d.ts +93 -0
- package/dist/config/index.js +5 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/index.d.ts +107 -0
- package/dist/core/index.js +5 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/index.d.ts +112 -0
- package/dist/layout/index.js +4 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/page/index.d.ts +87 -0
- package/dist/page/index.js +7 -0
- package/dist/page/index.js.map +1 -0
- package/dist/presets/index.d.ts +192 -0
- package/dist/presets/index.js +3 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/router/index.d.ts +104 -0
- package/dist/router/index.js +7 -0
- package/dist/router/index.js.map +1 -0
- package/dist/transition-manager-CuO0S_Yn.d.ts +62 -0
- package/dist/types-BT3SCjiY.d.ts +272 -0
- package/dist/view-transition-Hp-Q9vWJ.d.ts +97 -0
- package/package.json +110 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/react/components.tsx"],"names":[],"mappings":";;;;;AAwDA,IAAM,iBAAA,GAAoB,cAA6C,IAAI,CAAA;AA+BpE,IAAM,qBAAkD,CAAC;AAAA,EAC5D,QAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA,EAAS;AACb,CAAA,KAAM;AAEF,EAAA,MAAM,UAAA,GAAa,OAAiC,IAAI,CAAA;AAExD,EAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AACrB,IAAA,UAAA,CAAW,OAAA,GAAU,aAAA,IAAiB,uBAAA,CAAwB,MAAM,CAAA;AAAA,EACxE;AAEA,EAAA,MAAM,UAAU,UAAA,CAAW,OAAA;AAG3B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAI,QAAA,CAA0B,OAAA,CAAQ,UAAU,CAAA;AAGtE,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,SAAA,CAAU,CAAC,QAAA,KAAa;AAChD,MAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,IACrB,CAAC,CAAA;AACD,IAAA,OAAO,WAAA;AAAA,EACX,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAGZ,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,MAAA,EAAQ;AACR,MAAA,OAAA,CAAQ,UAAU,MAAM,CAAA;AAAA,IAC5B;AAAA,EACJ,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAO,CAAC,CAAA;AAGpB,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,OAAO,MAAM;AACT,MAAA,IAAI,CAAC,aAAA,EAAe;AAChB,QAAA,OAAA,CAAQ,OAAA,EAAQ;AAAA,MACpB;AAAA,IACJ,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,OAAA,EAAS,aAAa,CAAC,CAAA;AAE3B,EAAA,MAAM,KAAA,GAAQ,QAAgC,OAAO;AAAA,IACjD,KAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,IAC7B,yBAAA,EAA2B,QAAQ,yBAAA,EAA0B;AAAA,IAC7D,iBAAiB,CAAC,EAAA,EAAI,eAAe,OAAA,CAAQ,mBAAA,CAAoB,IAAI,UAAU,CAAA;AAAA,IAC/E,cAAA,EAAgB,MAAM,OAAA,CAAQ,cAAA;AAAe,GACjD,CAAA,EAAI,CAAC,KAAA,EAAO,OAAO,CAAC,CAAA;AAEpB,EAAA,uBACI,GAAA,CAAC,iBAAA,CAAkB,QAAA,EAAlB,EAA2B,OACvB,QAAA,EACL,CAAA;AAER;AAyBO,SAAS,aAAA,GAAwC;AACpD,EAAA,MAAM,OAAA,GAAU,WAAW,iBAAiB,CAAA;AAE5C,EAAA,IAAI,CAAC,OAAA,EAAS;AAEV,IAAA,MAAM,UAAU,oBAAA,EAAqB;AACrC,IAAA,OAAO;AAAA,MACH,KAAA,EAAO,QAAQ,QAAA,EAAS;AAAA,MACxB,OAAA;AAAA,MACA,SAAA,EAAW,QAAQ,SAAA,EAAU;AAAA,MAC7B,yBAAA,EAA2B,QAAQ,yBAAA,EAA0B;AAAA,MAC7D,iBAAiB,CAAC,EAAA,EAAI,WAAW,OAAA,CAAQ,mBAAA,CAAoB,IAAI,MAAM,CAAA;AAAA,MACvE,cAAA,EAAgB,MAAM,OAAA,CAAQ,cAAA;AAAe,KACjD;AAAA,EACJ;AAEA,EAAA,OAAO,OAAA;AACX;AAKO,SAAS,kBAAA,GAAsC;AAClD,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,EAAc;AAChC,EAAA,OAAO,KAAA;AACX;AAKO,SAAS,kBAAA,GAA8B;AAC1C,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,EAAc;AAChC,EAAA,OAAO,KAAA,CAAM,eAAA;AACjB;AAKO,SAAS,sBAAA,GAAsD;AAClE,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,EAAc;AAChC,EAAA,OAAO,KAAA,CAAM,SAAA;AACjB;AAKO,SAAS,gBAAA,GAA4B;AACxC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,IAAI,QAAA,CAAS,MAAM,sBAAsB,CAAA;AAEnE,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA;AAEvE,IAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAA+B;AAC5C,MAAA,UAAA,CAAW,MAAM,OAAO,CAAA;AAAA,IAC5B,CAAA;AAEA,IAAA,UAAA,CAAW,gBAAA,CAAiB,UAAU,OAAO,CAAA;AAC7C,IAAA,OAAO,MAAM,UAAA,CAAW,mBAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AAAA,EACjE,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,OAAA;AACX;AAuCO,IAAM,iBAA0C,CAAC;AAAA,EACpD,QAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA,GAAO,QAAA;AAAA,EACP,OAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA;AACJ,CAAA,KAAM;AACF,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,EAAc;AAChC,EAAA,MAAM,YAAA,GAAe,OAAuB,IAAI,CAAA;AAGhD,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,KAAA,CAAM,eAAA,IAAmB,KAAA,CAAM,KAAA,KAAU,SAAA,EAAW;AACpD,MAAA,OAAA,IAAU;AAAA,IACd;AACA,IAAA,IAAI,CAAC,KAAA,CAAM,eAAA,IAAmB,KAAA,CAAM,UAAU,MAAA,EAAQ;AAClD,MAAA,KAAA,IAAQ;AAAA,IACZ;AAAA,EACJ,CAAA,EAAG,CAAC,KAAA,CAAM,eAAA,EAAiB,MAAM,KAAA,EAAO,OAAA,EAAS,KAAK,CAAC,CAAA;AAGvD,EAAA,MAAM,eAAA,GAAkB,QAAQ,MAAM;AAClC,IAAA,MAAM,OAAA,GAAU,CAAC,wBAAwB,CAAA;AAEzC,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,OAAA,CAAQ,KAAK,SAAS,CAAA;AAAA,IAC1B;AAEA,IAAA,IAAI,MAAM,eAAA,EAAiB;AACvB,MAAA,OAAA,CAAQ,KAAK,sBAAsB,CAAA;AACnC,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,kBAAA,EAAqB,KAAA,CAAM,KAAK,CAAA,CAAE,CAAA;AAC/C,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,iBAAA,EAAoB,KAAA,CAAM,SAAS,CAAA,CAAE,CAAA;AAAA,IACtD;AAEA,IAAA,OAAO,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,EAC3B,CAAA,EAAG,CAAC,SAAA,EAAW,KAAA,CAAM,iBAAiB,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,SAAS,CAAC,CAAA;AAGnE,EAAA,MAAM,WAAA,GAAc,QAAuB,MAAM;AAC7C,IAAA,MAAM,MAAA,GAAwB,EAAE,GAAG,KAAA,EAAM;AAEzC,IAAA,IAAI,aAAa,MAAA,EAAW;AACxB,MAAC,MAAA,CAAmC,8BAA8B,CAAA,GAAI,CAAA,EAAG,QAAQ,CAAA,EAAA,CAAA;AAAA,IACrF;AAEA,IAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AAClC,MAAC,MAAA,CAAmC,0BAA0B,CAAA,GAAI,IAAA;AAAA,IACtE;AAEA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA,EAAG,CAAC,KAAA,EAAO,QAAA,EAAU,IAAI,CAAC,CAAA;AAE1B,EAAA,uBACI,GAAA,CAAC,SAAI,GAAA,EAAK,YAAA,EAAc,WAAW,eAAA,EAAiB,KAAA,EAAO,aACtD,QAAA,EACL,CAAA;AAER;AA+CO,IAAM,aAAyC,CAAC;AAAA,EACnD,QAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA,GAAO,MAAA;AAAA,EACP,QAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,aAAA,GAAgB,IAAA;AAAA,EAChB,OAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,eAAA;AAAA,EACA,IAAI,SAAA,GAAY,KAAA;AAAA,EAChB,SAAA;AAAA,EACA;AACJ,CAAA,KAAM;AACF,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA;AAAA,IACtB,OAAO,SAAA,GAAY;AAAA,GACvB;AACA,EAAA,MAAM,cAAA,GAAiB,OAAO,IAAI,CAAA;AAElC,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,UAAU,cAAA,CAAe,OAAA;AAC/B,IAAA,cAAA,CAAe,OAAA,GAAU,KAAA;AAEzB,IAAA,IAAI,IAAA,EAAM;AACN,MAAA,eAAA,CAAgB,IAAI,CAAA;AAEpB,MAAA,IAAI,CAAC,WAAW,MAAA,EAAQ;AACpB,QAAA,QAAA,CAAS,UAAU,CAAA;AACnB,QAAA,OAAA,IAAU;AAEV,QAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC3B,UAAA,QAAA,CAAS,SAAS,CAAA;AAClB,UAAA,eAAA,IAAkB;AAAA,QACtB,CAAA,EAAG,YAAY,GAAG,CAAA;AAElB,QAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,MACnC,CAAA,MAAO;AACH,QAAA,QAAA,CAAS,SAAS,CAAA;AAAA,MACtB;AAAA,IACJ,CAAA,MAAO;AACH,MAAA,QAAA,CAAS,SAAS,CAAA;AAClB,MAAA,OAAA,IAAU;AAEV,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC3B,QAAA,QAAA,CAAS,MAAM,CAAA;AACf,QAAA,eAAA,IAAkB;AAClB,QAAA,IAAI,aAAA,EAAe;AACf,UAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,QACzB;AAAA,MACJ,CAAA,EAAG,YAAY,GAAG,CAAA;AAElB,MAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,IACnC;AAAA,EACJ,CAAA,EAAG,CAAC,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAU,eAAe,OAAA,EAAS,eAAA,EAAiB,OAAA,EAAS,eAAe,CAAC,CAAA;AAE9F,EAAA,IAAI,CAAC,YAAA,EAAc;AACf,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,MAAM,eAAA,GAAkB;AAAA,IACpB,mBAAA;AAAA,IACA,qBAAqB,KAAK,CAAA,CAAA;AAAA,IAC1B,OAAO,IAAA,KAAS,QAAA,GAAW,CAAA,kBAAA,EAAqB,IAAI,CAAA,CAAA,GAAK,MAAA;AAAA,IACzD;AAAA,GACJ,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAE1B,EAAA,MAAM,WAAA,GAA6B;AAAA,IAC/B,GAAG;AAAA,GACP;AAEA,EAAA,IAAI,aAAa,MAAA,EAAW;AACxB,IAAC,WAAA,CAAwC,8BAA8B,CAAA,GAAI,CAAA,EAAG,QAAQ,CAAA,EAAA,CAAA;AAAA,EAC1F;AAEA,EAAA,OAAO,aAAA;AAAA,IACH,SAAA;AAAA,IACA,EAAE,SAAA,EAAW,eAAA,EAAiB,KAAA,EAAO,WAAA,EAAY;AAAA,IACjD;AAAA,GACJ;AACJ;AAkCO,IAAM,gBAAwC,CAAC;AAAA,EAClD,QAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAI,SAAA,GAAY,KAAA;AAAA,EAChB,SAAA;AAAA,EACA;AACJ,CAAA,KAAM;AACF,EAAA,MAAM,GAAA,GAAM,OAAoB,IAAI,CAAA;AAEpC,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,UAAU,GAAA,CAAI,OAAA;AACpB,IAAA,IAAI,OAAA,EAAS;AAET,MAAA,OAAA,CAAQ,MAAM,kBAAA,GAAqB,IAAA;AAEnC,MAAA,OAAO,MAAM;AACT,QAAA,OAAA,CAAQ,MAAM,kBAAA,GAAqB,EAAA;AAAA,MACvC,CAAA;AAAA,IACJ;AAAA,EACJ,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,OAAO,aAAA;AAAA,IACH,SAAA;AAAA,IACA;AAAA,MACI,GAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA;AAAA,MACA,sBAAA,EAAwB;AAAA,KAC5B;AAAA,IACA;AAAA,GACJ;AACJ;AA2BO,IAAM,iBAA0C,CAAC;AAAA,EACpD,QAAA;AAAA,EACA,IAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA,GAAU,KAAA;AAAA,EACV,QAAA,GAAW,KAAA;AAAA,EACX,OAAA;AAAA,EACA,GAAG;AACP,CAAA,KAAM;AACF,EAAA,MAAM,EAAE,eAAA,EAAiB,OAAA,EAAQ,GAAI,aAAA,EAAc;AAEnD,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAO,CAAA,KAA2C;AAE9E,IAAA,OAAA,GAAU,CAAC,CAAA;AAGX,IAAA,IAAI,EAAE,gBAAA,EAAkB;AAGxB,IAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,IAAK,CAAA,CAAE,OAAA,IAAW,EAAE,OAAA,IAAW,CAAA,CAAE,QAAA,IAAY,CAAA,CAAE,MAAA,EAAQ;AACpE,MAAA;AAAA,IACJ;AAGA,IAAA,IAAI,IAAA,IAAQ,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,IAAK,CAAC,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,EAAG;AAC3E,MAAA;AAAA,IACJ;AAGA,IAAA,CAAA,CAAE,cAAA,EAAe;AAEjB,IAAA,MAAM,UAAA,GAAa,IAAA,EAAM,UAAA,CAAW,GAAG,CAAA,GACjC,IAAA,GACA,IAAI,GAAA,CAAI,IAAA,IAAQ,EAAA,EAAI,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,CAAE,QAAA;AAGlD,IAAA,MAAM,eAAA,CAAgB,YAAY,UAAA,KAAe,MAAA,GAAY,EAAE,OAAA,EAAS,UAAA,KAAe,MAAS,CAAA;AAGhG,IAAA,IAAI,OAAA,EAAS;AACT,MAAA,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAa,EAAC,EAAG,IAAI,UAAU,CAAA;AAAA,IAClD,CAAA,MAAO;AACH,MAAA,MAAA,CAAO,OAAA,CAAQ,SAAA,CAAU,EAAC,EAAG,IAAI,UAAU,CAAA;AAAA,IAC/C;AAGA,IAAA,MAAA,CAAO,aAAA,CAAc,IAAI,aAAA,CAAc,UAAU,CAAC,CAAA;AAAA,EACtD,GAAG,CAAC,IAAA,EAAM,YAAY,OAAA,EAAS,OAAA,EAAS,eAAe,CAAC,CAAA;AAExD,EAAA,2BACK,GAAA,EAAA,EAAE,IAAA,EAAY,SAAS,WAAA,EAAc,GAAG,OACpC,QAAA,EACL,CAAA;AAER","file":"index.js","sourcesContent":["/**\r\n * @flight-framework/transitions - React Adapter\r\n * \r\n * React components and hooks for Flight Transitions.\r\n */\r\n\r\n'use client';\r\n\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useState,\r\n useEffect,\r\n useCallback,\r\n useRef,\r\n useMemo,\r\n createElement,\r\n type ReactNode,\r\n type FC,\r\n type CSSProperties,\r\n type ElementType,\r\n} from 'react';\r\n\r\nimport type {\r\n TransitionsConfig,\r\n TransitionState,\r\n TransitionPreset,\r\n CustomTransition,\r\n PageTransitionConfig,\r\n} from '../../core/types';\r\nimport {\r\n createTransitionManager,\r\n getTransitionManager,\r\n type TransitionManager,\r\n} from '../../core/transition-manager';\r\nimport { prefersReducedMotion } from '../../core/animation-engine';\r\n\r\n// =============================================================================\r\n// CONTEXT\r\n// =============================================================================\r\n\r\ninterface TransitionContextValue {\r\n /** Current transition state */\r\n state: TransitionState;\r\n /** Transition manager instance */\r\n manager: TransitionManager;\r\n /** Whether transitions are enabled */\r\n isEnabled: boolean;\r\n /** Whether View Transitions API is supported */\r\n isViewTransitionSupported: boolean;\r\n /** Start a page transition programmatically */\r\n startTransition: (to: string, config?: PageTransitionConfig) => Promise<void>;\r\n /** Skip the current transition */\r\n skipTransition: () => void;\r\n}\r\n\r\nconst TransitionContext = createContext<TransitionContextValue | null>(null);\r\n\r\n// =============================================================================\r\n// PROVIDER\r\n// =============================================================================\r\n\r\nexport interface TransitionProviderProps {\r\n children: ReactNode;\r\n /** Initial transition configuration */\r\n config?: TransitionsConfig;\r\n /** Use a custom transition manager */\r\n manager?: TransitionManager;\r\n}\r\n\r\n/**\r\n * TransitionProvider - Provides transition context to the app\r\n * \r\n * @example\r\n * ```tsx\r\n * // In your root layout\r\n * import { TransitionProvider } from '@flight-framework/transitions/react';\r\n * \r\n * export default function RootLayout({ children }) {\r\n * return (\r\n * <TransitionProvider config={{ pageTransition: 'fade' }}>\r\n * {children}\r\n * </TransitionProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const TransitionProvider: FC<TransitionProviderProps> = ({\r\n children,\r\n config,\r\n manager: customManager,\r\n}) => {\r\n // Create or use provided manager\r\n const managerRef = useRef<TransitionManager | null>(null);\r\n\r\n if (!managerRef.current) {\r\n managerRef.current = customManager ?? createTransitionManager(config);\r\n }\r\n\r\n const manager = managerRef.current;\r\n\r\n // Track transition state\r\n const [state, setState] = useState<TransitionState>(manager.getState());\r\n\r\n // Subscribe to state changes\r\n useEffect(() => {\r\n const unsubscribe = manager.subscribe((newState) => {\r\n setState(newState);\r\n });\r\n return unsubscribe;\r\n }, [manager]);\r\n\r\n // Update config when it changes\r\n useEffect(() => {\r\n if (config) {\r\n manager.configure(config);\r\n }\r\n }, [config, manager]);\r\n\r\n // Cleanup on unmount\r\n useEffect(() => {\r\n return () => {\r\n if (!customManager) {\r\n manager.destroy();\r\n }\r\n };\r\n }, [manager, customManager]);\r\n\r\n const value = useMemo<TransitionContextValue>(() => ({\r\n state,\r\n manager,\r\n isEnabled: manager.isEnabled(),\r\n isViewTransitionSupported: manager.isViewTransitionSupported(),\r\n startTransition: (to, pageConfig) => manager.startPageTransition(to, pageConfig),\r\n skipTransition: () => manager.skipTransition(),\r\n }), [state, manager]);\r\n\r\n return (\r\n <TransitionContext.Provider value={value}>\r\n {children}\r\n </TransitionContext.Provider>\r\n );\r\n};\r\n\r\n// =============================================================================\r\n// HOOKS\r\n// =============================================================================\r\n\r\n/**\r\n * useTransition - Access the transition context\r\n * \r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { state, startTransition } = useTransition();\r\n * \r\n * return (\r\n * <div>\r\n * {state.isTransitioning && <LoadingSpinner />}\r\n * <button onClick={() => startTransition('/about')}>\r\n * Go to About\r\n * </button>\r\n * </div>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function useTransition(): TransitionContextValue {\r\n const context = useContext(TransitionContext);\r\n\r\n if (!context) {\r\n // Return a fallback for components outside provider\r\n const manager = getTransitionManager();\r\n return {\r\n state: manager.getState(),\r\n manager,\r\n isEnabled: manager.isEnabled(),\r\n isViewTransitionSupported: manager.isViewTransitionSupported(),\r\n startTransition: (to, config) => manager.startPageTransition(to, config),\r\n skipTransition: () => manager.skipTransition(),\r\n };\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * useTransitionState - Get just the transition state\r\n */\r\nexport function useTransitionState(): TransitionState {\r\n const { state } = useTransition();\r\n return state;\r\n}\r\n\r\n/**\r\n * useIsTransitioning - Check if a transition is in progress\r\n */\r\nexport function useIsTransitioning(): boolean {\r\n const { state } = useTransition();\r\n return state.isTransitioning;\r\n}\r\n\r\n/**\r\n * useTransitionDirection - Get the current transition direction\r\n */\r\nexport function useTransitionDirection(): 'forward' | 'back' | 'auto' {\r\n const { state } = useTransition();\r\n return state.direction;\r\n}\r\n\r\n/**\r\n * useReducedMotion - Check if user prefers reduced motion\r\n */\r\nexport function useReducedMotion(): boolean {\r\n const [reduced, setReduced] = useState(() => prefersReducedMotion());\r\n\r\n useEffect(() => {\r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n\r\n const handler = (event: MediaQueryListEvent) => {\r\n setReduced(event.matches);\r\n };\r\n\r\n mediaQuery.addEventListener('change', handler);\r\n return () => mediaQuery.removeEventListener('change', handler);\r\n }, []);\r\n\r\n return reduced;\r\n}\r\n\r\n// =============================================================================\r\n// PAGE TRANSITION COMPONENT\r\n// =============================================================================\r\n\r\nexport interface PageTransitionProps {\r\n children: ReactNode;\r\n /** Transition type (overrides context config) */\r\n type?: TransitionPreset | CustomTransition;\r\n /** Duration override */\r\n duration?: number;\r\n /** Mode for sequencing enter/leave */\r\n mode?: 'in-out' | 'out-in' | 'simultaneous';\r\n /** Callback when transition starts */\r\n onStart?: () => void;\r\n /** Callback when transition ends */\r\n onEnd?: () => void;\r\n /** CSS class for the wrapper */\r\n className?: string;\r\n /** Inline styles for the wrapper */\r\n style?: CSSProperties;\r\n}\r\n\r\n/**\r\n * PageTransition - Wraps page content with transition animations\r\n * \r\n * @example\r\n * ```tsx\r\n * // In a layout\r\n * export default function Layout({ children }) {\r\n * return (\r\n * <PageTransition type=\"slide-left\">\r\n * {children}\r\n * </PageTransition>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const PageTransition: FC<PageTransitionProps> = ({\r\n children,\r\n type,\r\n duration,\r\n mode = 'out-in',\r\n onStart,\r\n onEnd,\r\n className,\r\n style,\r\n}) => {\r\n const { state } = useTransition();\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n\r\n // Call callbacks\r\n useEffect(() => {\r\n if (state.isTransitioning && state.phase === 'leaving') {\r\n onStart?.();\r\n }\r\n if (!state.isTransitioning && state.phase === 'idle') {\r\n onEnd?.();\r\n }\r\n }, [state.isTransitioning, state.phase, onStart, onEnd]);\r\n\r\n // Build transition class\r\n const transitionClass = useMemo(() => {\r\n const classes = ['flight-page-transition'];\r\n\r\n if (className) {\r\n classes.push(className);\r\n }\r\n\r\n if (state.isTransitioning) {\r\n classes.push('flight-transitioning');\r\n classes.push(`flight-transition-${state.phase}`);\r\n classes.push(`flight-direction-${state.direction}`);\r\n }\r\n\r\n return classes.join(' ');\r\n }, [className, state.isTransitioning, state.phase, state.direction]);\r\n\r\n // Build inline styles with CSS custom properties\r\n const inlineStyle = useMemo<CSSProperties>(() => {\r\n const styles: CSSProperties = { ...style };\r\n\r\n if (duration !== undefined) {\r\n (styles as Record<string, unknown>)['--flight-transition-duration'] = `${duration}ms`;\r\n }\r\n\r\n if (type && typeof type === 'string') {\r\n (styles as Record<string, unknown>)['--flight-transition-type'] = type;\r\n }\r\n\r\n return styles;\r\n }, [style, duration, type]);\r\n\r\n return (\r\n <div ref={containerRef} className={transitionClass} style={inlineStyle}>\r\n {children}\r\n </div>\r\n );\r\n};\r\n\r\n// =============================================================================\r\n// TRANSITION COMPONENT (for elements)\r\n// =============================================================================\r\n\r\nexport interface TransitionElementProps {\r\n children: ReactNode;\r\n /** Show or hide the element */\r\n show: boolean;\r\n /** Transition type */\r\n type?: TransitionPreset | CustomTransition;\r\n /** Duration override */\r\n duration?: number;\r\n /** Animate on initial mount */\r\n appear?: boolean;\r\n /** Unmount when hidden */\r\n unmountOnHide?: boolean;\r\n /** Callbacks */\r\n onEnter?: () => void;\r\n onEnterComplete?: () => void;\r\n onLeave?: () => void;\r\n onLeaveComplete?: () => void;\r\n /** Wrapper element tag name */\r\n as?: 'div' | 'span' | 'section' | 'article' | 'main' | 'aside' | 'header' | 'footer' | 'nav';\r\n /** CSS class */\r\n className?: string;\r\n /** Inline styles */\r\n style?: CSSProperties;\r\n}\r\n\r\n/**\r\n * Transition - Animate element enter/leave\r\n * \r\n * @example\r\n * ```tsx\r\n * function Modal({ isOpen, onClose, children }) {\r\n * return (\r\n * <Transition show={isOpen} type=\"fade-scale\">\r\n * <div className=\"modal\">\r\n * {children}\r\n * </div>\r\n * </Transition>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const Transition: FC<TransitionElementProps> = ({\r\n children,\r\n show,\r\n type = 'fade',\r\n duration,\r\n appear = false,\r\n unmountOnHide = true,\r\n onEnter,\r\n onEnterComplete,\r\n onLeave,\r\n onLeaveComplete,\r\n as: Component = 'div',\r\n className,\r\n style,\r\n}) => {\r\n const [shouldRender, setShouldRender] = useState(show);\r\n const [phase, setPhase] = useState<'entering' | 'entered' | 'leaving' | 'left'>(\r\n show ? 'entered' : 'left'\r\n );\r\n const isInitialMount = useRef(true);\r\n\r\n useEffect(() => {\r\n const isMount = isInitialMount.current;\r\n isInitialMount.current = false;\r\n\r\n if (show) {\r\n setShouldRender(true);\r\n\r\n if (!isMount || appear) {\r\n setPhase('entering');\r\n onEnter?.();\r\n\r\n const timer = setTimeout(() => {\r\n setPhase('entered');\r\n onEnterComplete?.();\r\n }, duration ?? 200);\r\n\r\n return () => clearTimeout(timer);\r\n } else {\r\n setPhase('entered');\r\n }\r\n } else {\r\n setPhase('leaving');\r\n onLeave?.();\r\n\r\n const timer = setTimeout(() => {\r\n setPhase('left');\r\n onLeaveComplete?.();\r\n if (unmountOnHide) {\r\n setShouldRender(false);\r\n }\r\n }, duration ?? 200);\r\n\r\n return () => clearTimeout(timer);\r\n }\r\n }, [show, appear, duration, unmountOnHide, onEnter, onEnterComplete, onLeave, onLeaveComplete]);\r\n\r\n if (!shouldRender) {\r\n return null;\r\n }\r\n\r\n const transitionClass = [\r\n 'flight-transition',\r\n `flight-transition-${phase}`,\r\n typeof type === 'string' ? `flight-transition-${type}` : undefined,\r\n className,\r\n ].filter(Boolean).join(' ');\r\n\r\n const inlineStyle: CSSProperties = {\r\n ...style,\r\n };\r\n\r\n if (duration !== undefined) {\r\n (inlineStyle as Record<string, unknown>)['--flight-transition-duration'] = `${duration}ms`;\r\n }\r\n\r\n return createElement(\r\n Component,\r\n { className: transitionClass, style: inlineStyle },\r\n children\r\n );\r\n};\r\n\r\n// =============================================================================\r\n// SHARED ELEMENT\r\n// =============================================================================\r\n\r\nexport interface SharedElementProps {\r\n children: ReactNode;\r\n /** Unique name for matching across pages */\r\n name: string;\r\n /** Wrapper element tag name */\r\n as?: 'div' | 'span' | 'section' | 'article' | 'main' | 'aside' | 'header' | 'footer' | 'img';\r\n /** CSS class */\r\n className?: string;\r\n /** Inline styles */\r\n style?: CSSProperties;\r\n}\r\n\r\n/**\r\n * SharedElement - Mark an element for shared element transitions\r\n * \r\n * @example\r\n * ```tsx\r\n * // On list page\r\n * <SharedElement name={`product-${product.id}`}>\r\n * <img src={product.image} />\r\n * </SharedElement>\r\n * \r\n * // On detail page\r\n * <SharedElement name={`product-${product.id}`}>\r\n * <img src={product.image} />\r\n * </SharedElement>\r\n * ```\r\n */\r\nexport const SharedElement: FC<SharedElementProps> = ({\r\n children,\r\n name,\r\n as: Component = 'div',\r\n className,\r\n style,\r\n}) => {\r\n const ref = useRef<HTMLElement>(null);\r\n\r\n useEffect(() => {\r\n const element = ref.current;\r\n if (element) {\r\n // Set view-transition-name for native View Transitions API\r\n element.style.viewTransitionName = name;\r\n\r\n return () => {\r\n element.style.viewTransitionName = '';\r\n };\r\n }\r\n }, [name]);\r\n\r\n return createElement(\r\n Component,\r\n {\r\n ref: ref as React.Ref<HTMLDivElement>,\r\n className,\r\n style,\r\n 'data-transition-name': name,\r\n },\r\n children\r\n );\r\n};\r\n\r\n// =============================================================================\r\n// ANIMATED LINK\r\n// =============================================================================\r\n\r\nexport interface TransitionLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\r\n /** Transition type for this navigation */\r\n transition?: TransitionPreset | CustomTransition | false;\r\n /** Replace instead of push */\r\n replace?: boolean;\r\n /** Prefetch on hover */\r\n prefetch?: boolean;\r\n}\r\n\r\n/**\r\n * TransitionLink - Link component with transition support\r\n * \r\n * Use with @flight-framework/router or wrap your router's Link component.\r\n * \r\n * @example\r\n * ```tsx\r\n * <TransitionLink href=\"/about\" transition=\"slide-left\">\r\n * About Us\r\n * </TransitionLink>\r\n * ```\r\n */\r\nexport const TransitionLink: FC<TransitionLinkProps> = ({\r\n children,\r\n href,\r\n transition,\r\n replace = false,\r\n prefetch = false,\r\n onClick,\r\n ...props\r\n}) => {\r\n const { startTransition, manager } = useTransition();\r\n\r\n const handleClick = useCallback(async (e: React.MouseEvent<HTMLAnchorElement>) => {\r\n // Call original onClick if provided\r\n onClick?.(e);\r\n\r\n // If default prevented, don't handle\r\n if (e.defaultPrevented) return;\r\n\r\n // Only handle left clicks without modifiers\r\n if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {\r\n return;\r\n }\r\n\r\n // Only handle same-origin links\r\n if (href && !href.startsWith('/') && !href.startsWith(window.location.origin)) {\r\n return;\r\n }\r\n\r\n // Prevent default navigation\r\n e.preventDefault();\r\n\r\n const targetPath = href?.startsWith('/')\r\n ? href\r\n : new URL(href ?? '', window.location.origin).pathname;\r\n\r\n // Start transition\r\n await startTransition(targetPath, transition !== undefined ? { default: transition } : undefined);\r\n\r\n // Perform actual navigation\r\n if (replace) {\r\n window.history.replaceState({}, '', targetPath);\r\n } else {\r\n window.history.pushState({}, '', targetPath);\r\n }\r\n\r\n // Dispatch popstate for router to pick up\r\n window.dispatchEvent(new PopStateEvent('popstate'));\r\n }, [href, transition, replace, onClick, startTransition]);\r\n\r\n return (\r\n <a href={href} onClick={handleClick} {...props}>\r\n {children}\r\n </a>\r\n );\r\n};\r\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { i as isViewTransitionSupported, s as startViewTransition } from '../../view-transition-Hp-Q9vWJ.js';
|
|
2
|
+
export { c as createTransitionManager, g as getTransitionManager } from '../../transition-manager-CuO0S_Yn.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../page/index.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../layout/index.js';
|
|
5
|
+
import '../../types-BT3SCjiY.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import '../../chunk-W7HSR35B.js';
|
|
2
|
+
import '../../chunk-XLVYHPII.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../chunk-ITLC6KJ4.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../chunk-BAILQEFB.js';
|
|
5
|
+
import '../../chunk-ZBJ6FSAK.js';
|
|
6
|
+
export { createTransitionManager, getTransitionManager, isViewTransitionSupported, startViewTransition } from '../../chunk-7R3FXL3A.js';
|
|
7
|
+
import '../../chunk-4SF4GHDQ.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { i as isViewTransitionSupported, s as startViewTransition } from '../../view-transition-Hp-Q9vWJ.js';
|
|
2
|
+
export { c as createTransitionManager, g as getTransitionManager } from '../../transition-manager-CuO0S_Yn.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../page/index.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../layout/index.js';
|
|
5
|
+
import '../../types-BT3SCjiY.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import '../../chunk-W7HSR35B.js';
|
|
2
|
+
import '../../chunk-XLVYHPII.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../chunk-ITLC6KJ4.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../chunk-BAILQEFB.js';
|
|
5
|
+
import '../../chunk-ZBJ6FSAK.js';
|
|
6
|
+
export { createTransitionManager, getTransitionManager, isViewTransitionSupported, startViewTransition } from '../../chunk-7R3FXL3A.js';
|
|
7
|
+
import '../../chunk-4SF4GHDQ.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { i as isViewTransitionSupported, s as startViewTransition } from '../../view-transition-Hp-Q9vWJ.js';
|
|
2
|
+
export { c as createTransitionManager, g as getTransitionManager } from '../../transition-manager-CuO0S_Yn.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../page/index.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../layout/index.js';
|
|
5
|
+
import '../../types-BT3SCjiY.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import '../../chunk-W7HSR35B.js';
|
|
2
|
+
import '../../chunk-XLVYHPII.js';
|
|
3
|
+
export { definePageTransition, executePageTransition } from '../../chunk-ITLC6KJ4.js';
|
|
4
|
+
export { registerSharedElement, unregisterSharedElement } from '../../chunk-BAILQEFB.js';
|
|
5
|
+
import '../../chunk-ZBJ6FSAK.js';
|
|
6
|
+
export { createTransitionManager, getTransitionManager, isViewTransitionSupported, startViewTransition } from '../../chunk-7R3FXL3A.js';
|
|
7
|
+
import '../../chunk-4SF4GHDQ.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// src/core/animation-engine.ts
|
|
2
|
+
var DEFAULT_DURATION = 200;
|
|
3
|
+
var DEFAULT_EASING = "cubic-bezier(0.4, 0, 0.2, 1)";
|
|
4
|
+
var REDUCED_MOTION_DURATION = 1;
|
|
5
|
+
function animate(element, keyframe, options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
duration = DEFAULT_DURATION,
|
|
8
|
+
easing = DEFAULT_EASING,
|
|
9
|
+
delay = 0,
|
|
10
|
+
fill = "both",
|
|
11
|
+
onStart,
|
|
12
|
+
onComplete,
|
|
13
|
+
onCancel
|
|
14
|
+
} = options;
|
|
15
|
+
const keyframes = [
|
|
16
|
+
convertToKeyframe(keyframe.from),
|
|
17
|
+
convertToKeyframe(keyframe.to)
|
|
18
|
+
];
|
|
19
|
+
const animation = element.animate(keyframes, {
|
|
20
|
+
duration,
|
|
21
|
+
easing,
|
|
22
|
+
delay,
|
|
23
|
+
fill
|
|
24
|
+
});
|
|
25
|
+
if (onStart) {
|
|
26
|
+
animation.ready.then(onStart);
|
|
27
|
+
}
|
|
28
|
+
const finished = animation.finished.then(() => {
|
|
29
|
+
onComplete?.();
|
|
30
|
+
}).catch((error) => {
|
|
31
|
+
if (error.name === "AbortError") {
|
|
32
|
+
onCancel?.();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
animation,
|
|
37
|
+
finished,
|
|
38
|
+
cancel: () => {
|
|
39
|
+
animation.cancel();
|
|
40
|
+
},
|
|
41
|
+
pause: () => {
|
|
42
|
+
animation.pause();
|
|
43
|
+
},
|
|
44
|
+
resume: () => {
|
|
45
|
+
animation.play();
|
|
46
|
+
},
|
|
47
|
+
reverse: () => {
|
|
48
|
+
animation.reverse();
|
|
49
|
+
},
|
|
50
|
+
seek: (progress) => {
|
|
51
|
+
const time = progress * (duration + delay);
|
|
52
|
+
animation.currentTime = time;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function animateOut(element, transition, options) {
|
|
57
|
+
const { leave } = transition;
|
|
58
|
+
return animateWithKeyframes(element, leave.keyframes, {
|
|
59
|
+
...leave.options,
|
|
60
|
+
...options
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function animateIn(element, transition, options) {
|
|
64
|
+
const { enter } = transition;
|
|
65
|
+
return animateWithKeyframes(element, enter.keyframes, {
|
|
66
|
+
...enter.options,
|
|
67
|
+
...options
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function animateWithKeyframes(element, keyframes, options) {
|
|
71
|
+
const { onStart, onComplete, onCancel, ...animOptions } = options;
|
|
72
|
+
const animation = element.animate(keyframes, animOptions);
|
|
73
|
+
if (onStart) {
|
|
74
|
+
animation.ready.then(onStart);
|
|
75
|
+
}
|
|
76
|
+
const finished = animation.finished.then(() => {
|
|
77
|
+
onComplete?.();
|
|
78
|
+
}).catch((error) => {
|
|
79
|
+
if (error.name === "AbortError") {
|
|
80
|
+
onCancel?.();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
animation,
|
|
85
|
+
finished,
|
|
86
|
+
cancel: () => animation.cancel(),
|
|
87
|
+
pause: () => animation.pause(),
|
|
88
|
+
resume: () => animation.play(),
|
|
89
|
+
reverse: () => animation.reverse(),
|
|
90
|
+
seek: (progress) => {
|
|
91
|
+
const duration = typeof animOptions.duration === "number" ? animOptions.duration : 0;
|
|
92
|
+
animation.currentTime = progress * duration;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function convertToKeyframe(properties) {
|
|
97
|
+
const keyframe = {};
|
|
98
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
99
|
+
if (value !== void 0) {
|
|
100
|
+
const camelKey = kebabToCamel(key);
|
|
101
|
+
keyframe[camelKey] = value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return keyframe;
|
|
105
|
+
}
|
|
106
|
+
function kebabToCamel(str) {
|
|
107
|
+
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
108
|
+
}
|
|
109
|
+
function resolveTransition(input, reducedMotion = false) {
|
|
110
|
+
if (input === false) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const base = typeof input === "string" ? getPresetTransition(input) : normalizeCustomTransition(input);
|
|
114
|
+
if (!base) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
if (reducedMotion) {
|
|
118
|
+
return applyReducedMotion(base);
|
|
119
|
+
}
|
|
120
|
+
return base;
|
|
121
|
+
}
|
|
122
|
+
function getPresetTransition(name) {
|
|
123
|
+
switch (name) {
|
|
124
|
+
case "none":
|
|
125
|
+
return {
|
|
126
|
+
name: "none",
|
|
127
|
+
leave: {
|
|
128
|
+
keyframes: [{ opacity: 1 }, { opacity: 1 }],
|
|
129
|
+
options: { duration: 0, easing: "linear", fill: "both" }
|
|
130
|
+
},
|
|
131
|
+
enter: {
|
|
132
|
+
keyframes: [{ opacity: 1 }, { opacity: 1 }],
|
|
133
|
+
options: { duration: 0, easing: "linear", fill: "both" }
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
case "fade":
|
|
137
|
+
return {
|
|
138
|
+
name: "fade",
|
|
139
|
+
leave: {
|
|
140
|
+
keyframes: [{ opacity: 1 }, { opacity: 0 }],
|
|
141
|
+
options: { duration: 150, easing: "ease-out", fill: "both" }
|
|
142
|
+
},
|
|
143
|
+
enter: {
|
|
144
|
+
keyframes: [{ opacity: 0 }, { opacity: 1 }],
|
|
145
|
+
options: { duration: 150, easing: "ease-in", fill: "both" }
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
default:
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function normalizeCustomTransition(custom) {
|
|
153
|
+
const name = custom.name || "custom";
|
|
154
|
+
const leaveDuration = typeof custom.duration === "number" ? custom.duration : custom.duration?.leave ?? DEFAULT_DURATION;
|
|
155
|
+
const enterDuration = typeof custom.duration === "number" ? custom.duration : custom.duration?.enter ?? DEFAULT_DURATION;
|
|
156
|
+
const leaveEasing = typeof custom.easing === "string" ? custom.easing : custom.easing?.leave ?? DEFAULT_EASING;
|
|
157
|
+
const enterEasing = typeof custom.easing === "string" ? custom.easing : custom.easing?.enter ?? DEFAULT_EASING;
|
|
158
|
+
const leaveDelay = typeof custom.delay === "number" ? custom.delay : custom.delay?.leave ?? 0;
|
|
159
|
+
const enterDelay = typeof custom.delay === "number" ? custom.delay : custom.delay?.enter ?? 0;
|
|
160
|
+
const fill = custom.fill ?? "both";
|
|
161
|
+
return {
|
|
162
|
+
name,
|
|
163
|
+
leave: {
|
|
164
|
+
keyframes: custom.leave ? [convertToKeyframe(custom.leave.from), convertToKeyframe(custom.leave.to)] : [{ opacity: 1 }, { opacity: 0 }],
|
|
165
|
+
options: {
|
|
166
|
+
duration: leaveDuration,
|
|
167
|
+
easing: leaveEasing,
|
|
168
|
+
delay: leaveDelay,
|
|
169
|
+
fill
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
enter: {
|
|
173
|
+
keyframes: custom.enter ? [convertToKeyframe(custom.enter.from), convertToKeyframe(custom.enter.to)] : [{ opacity: 0 }, { opacity: 1 }],
|
|
174
|
+
options: {
|
|
175
|
+
duration: enterDuration,
|
|
176
|
+
easing: enterEasing,
|
|
177
|
+
delay: enterDelay,
|
|
178
|
+
fill
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function applyReducedMotion(transition) {
|
|
184
|
+
return {
|
|
185
|
+
...transition,
|
|
186
|
+
name: `${transition.name}-reduced`,
|
|
187
|
+
leave: {
|
|
188
|
+
...transition.leave,
|
|
189
|
+
options: {
|
|
190
|
+
...transition.leave.options,
|
|
191
|
+
duration: REDUCED_MOTION_DURATION
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
enter: {
|
|
195
|
+
...transition.enter,
|
|
196
|
+
options: {
|
|
197
|
+
...transition.enter.options,
|
|
198
|
+
duration: REDUCED_MOTION_DURATION
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function prefersReducedMotion() {
|
|
204
|
+
if (typeof window === "undefined") return false;
|
|
205
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
206
|
+
}
|
|
207
|
+
function onReducedMotionChange(callback) {
|
|
208
|
+
if (typeof window === "undefined") {
|
|
209
|
+
return () => {
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
213
|
+
const handler = (event) => {
|
|
214
|
+
callback(event.matches);
|
|
215
|
+
};
|
|
216
|
+
mediaQuery.addEventListener("change", handler);
|
|
217
|
+
return () => {
|
|
218
|
+
mediaQuery.removeEventListener("change", handler);
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function cancelAnimations(element) {
|
|
222
|
+
element.getAnimations().forEach((anim) => anim.cancel());
|
|
223
|
+
}
|
|
224
|
+
async function waitForAnimations(element) {
|
|
225
|
+
const animations = element.getAnimations();
|
|
226
|
+
await Promise.all(animations.map((anim) => anim.finished));
|
|
227
|
+
}
|
|
228
|
+
function flip(element, callback, options = {}) {
|
|
229
|
+
const first = element.getBoundingClientRect();
|
|
230
|
+
callback();
|
|
231
|
+
const last = element.getBoundingClientRect();
|
|
232
|
+
const deltaX = first.left - last.left;
|
|
233
|
+
const deltaY = first.top - last.top;
|
|
234
|
+
const deltaW = first.width / last.width;
|
|
235
|
+
const deltaH = first.height / last.height;
|
|
236
|
+
return animate(element, {
|
|
237
|
+
from: {
|
|
238
|
+
transform: `translate(${deltaX}px, ${deltaY}px) scale(${deltaW}, ${deltaH})`
|
|
239
|
+
},
|
|
240
|
+
to: {
|
|
241
|
+
transform: "translate(0, 0) scale(1, 1)"
|
|
242
|
+
}
|
|
243
|
+
}, {
|
|
244
|
+
duration: options.duration ?? 300,
|
|
245
|
+
easing: options.easing ?? "cubic-bezier(0.2, 0, 0.2, 1)",
|
|
246
|
+
...options
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export { DEFAULT_DURATION, DEFAULT_EASING, REDUCED_MOTION_DURATION, animate, animateIn, animateOut, cancelAnimations, flip, onReducedMotionChange, prefersReducedMotion, resolveTransition, waitForAnimations };
|
|
251
|
+
//# sourceMappingURL=chunk-4SF4GHDQ.js.map
|
|
252
|
+
//# sourceMappingURL=chunk-4SF4GHDQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/animation-engine.ts"],"names":[],"mappings":"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","file":"chunk-4SF4GHDQ.js","sourcesContent":["/**\r\n * @flight-framework/transitions - Animation Engine\r\n * \r\n * Low-level animation primitives using the Web Animations API.\r\n * Provides performant, interruptible animations with proper cleanup.\r\n */\r\n\r\nimport type {\r\n TransitionKeyframe,\r\n CustomTransition,\r\n ResolvedTransition,\r\n TransitionPreset,\r\n FillMode,\r\n} from './types';\r\n\r\n// =============================================================================\r\n// CONSTANTS\r\n// =============================================================================\r\n\r\n/** Default animation duration in milliseconds */\r\nexport const DEFAULT_DURATION = 200;\r\n\r\n/** Default easing function */\r\nexport const DEFAULT_EASING = 'cubic-bezier(0.4, 0, 0.2, 1)';\r\n\r\n/** Reduced motion duration (near-instant) */\r\nexport const REDUCED_MOTION_DURATION = 1;\r\n\r\n// =============================================================================\r\n// ANIMATION ENGINE\r\n// =============================================================================\r\n\r\n/**\r\n * Options for creating an animation\r\n */\r\nexport interface AnimationOptions {\r\n /** Animation duration in milliseconds */\r\n duration?: number;\r\n /** CSS easing function */\r\n easing?: string;\r\n /** Delay before animation starts */\r\n delay?: number;\r\n /** Animation fill mode */\r\n fill?: FillMode;\r\n /** Callback when animation starts */\r\n onStart?: () => void;\r\n /** Callback when animation completes */\r\n onComplete?: () => void;\r\n /** Callback when animation is cancelled */\r\n onCancel?: () => void;\r\n}\r\n\r\n/**\r\n * Result from creating an animation\r\n */\r\nexport interface AnimationHandle {\r\n /** The underlying Animation object */\r\n animation: Animation;\r\n /** Promise that resolves when animation finishes */\r\n finished: Promise<void>;\r\n /** Cancel the animation */\r\n cancel(): void;\r\n /** Pause the animation */\r\n pause(): void;\r\n /** Resume a paused animation */\r\n resume(): void;\r\n /** Reverse the animation direction */\r\n reverse(): void;\r\n /** Set the current time (0-1 normalized) */\r\n seek(progress: number): void;\r\n}\r\n\r\n/**\r\n * Animate an element with keyframes\r\n * \r\n * Uses the Web Animations API for smooth, performant animations.\r\n * \r\n * @example\r\n * ```typescript\r\n * const handle = animate(element, {\r\n * from: { opacity: '1', transform: 'scale(1)' },\r\n * to: { opacity: '0', transform: 'scale(0.95)' }\r\n * }, { duration: 200 });\r\n * \r\n * await handle.finished;\r\n * ```\r\n */\r\nexport function animate(\r\n element: Element,\r\n keyframe: TransitionKeyframe,\r\n options: AnimationOptions = {}\r\n): AnimationHandle {\r\n const {\r\n duration = DEFAULT_DURATION,\r\n easing = DEFAULT_EASING,\r\n delay = 0,\r\n fill = 'both',\r\n onStart,\r\n onComplete,\r\n onCancel,\r\n } = options;\r\n\r\n // Convert TransitionKeyframe to Web Animations API format\r\n const keyframes: Keyframe[] = [\r\n convertToKeyframe(keyframe.from),\r\n convertToKeyframe(keyframe.to),\r\n ];\r\n\r\n // Create the animation\r\n const animation = element.animate(keyframes, {\r\n duration,\r\n easing,\r\n delay,\r\n fill,\r\n });\r\n\r\n // Call onStart when animation begins\r\n if (onStart) {\r\n animation.ready.then(onStart);\r\n }\r\n\r\n // Create finished promise with callbacks\r\n const finished = animation.finished.then(() => {\r\n onComplete?.();\r\n }).catch((error) => {\r\n // Animation was cancelled\r\n if (error.name === 'AbortError') {\r\n onCancel?.();\r\n }\r\n });\r\n\r\n return {\r\n animation,\r\n finished,\r\n cancel: () => {\r\n animation.cancel();\r\n },\r\n pause: () => {\r\n animation.pause();\r\n },\r\n resume: () => {\r\n animation.play();\r\n },\r\n reverse: () => {\r\n animation.reverse();\r\n },\r\n seek: (progress: number) => {\r\n const time = progress * (duration + delay);\r\n animation.currentTime = time;\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Animate an element out (leaving)\r\n */\r\nexport function animateOut(\r\n element: Element,\r\n transition: ResolvedTransition,\r\n options?: Omit<AnimationOptions, 'duration' | 'easing'>\r\n): AnimationHandle {\r\n const { leave } = transition;\r\n\r\n return animateWithKeyframes(element, leave.keyframes, {\r\n ...leave.options,\r\n ...options,\r\n });\r\n}\r\n\r\n/**\r\n * Animate an element in (entering)\r\n */\r\nexport function animateIn(\r\n element: Element,\r\n transition: ResolvedTransition,\r\n options?: Omit<AnimationOptions, 'duration' | 'easing'>\r\n): AnimationHandle {\r\n const { enter } = transition;\r\n\r\n return animateWithKeyframes(element, enter.keyframes, {\r\n ...enter.options,\r\n ...options,\r\n });\r\n}\r\n\r\n/**\r\n * Animate with raw keyframes\r\n */\r\nfunction animateWithKeyframes(\r\n element: Element,\r\n keyframes: Keyframe[],\r\n options: KeyframeAnimationOptions & {\r\n onStart?: () => void;\r\n onComplete?: () => void;\r\n onCancel?: () => void;\r\n }\r\n): AnimationHandle {\r\n const { onStart, onComplete, onCancel, ...animOptions } = options;\r\n\r\n const animation = element.animate(keyframes, animOptions);\r\n\r\n if (onStart) {\r\n animation.ready.then(onStart);\r\n }\r\n\r\n const finished = animation.finished.then(() => {\r\n onComplete?.();\r\n }).catch((error) => {\r\n if (error.name === 'AbortError') {\r\n onCancel?.();\r\n }\r\n });\r\n\r\n return {\r\n animation,\r\n finished,\r\n cancel: () => animation.cancel(),\r\n pause: () => animation.pause(),\r\n resume: () => animation.play(),\r\n reverse: () => animation.reverse(),\r\n seek: (progress: number) => {\r\n const duration = typeof animOptions.duration === 'number'\r\n ? animOptions.duration\r\n : 0;\r\n animation.currentTime = progress * duration;\r\n },\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// KEYFRAME CONVERSION\r\n// =============================================================================\r\n\r\n/**\r\n * Convert CSS property object to Web Animations API Keyframe\r\n */\r\nfunction convertToKeyframe(\r\n properties: Partial<Record<string, string>>\r\n): Keyframe {\r\n const keyframe: Keyframe = {};\r\n\r\n for (const [key, value] of Object.entries(properties)) {\r\n if (value !== undefined) {\r\n // Convert kebab-case to camelCase\r\n const camelKey = kebabToCamel(key);\r\n (keyframe as Record<string, string>)[camelKey] = value;\r\n }\r\n }\r\n\r\n return keyframe;\r\n}\r\n\r\n/**\r\n * Convert kebab-case to camelCase\r\n */\r\nfunction kebabToCamel(str: string): string {\r\n return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\r\n}\r\n\r\n// =============================================================================\r\n// TRANSITION RESOLUTION\r\n// =============================================================================\r\n\r\n/**\r\n * Resolve a preset name or custom transition to a normalized format\r\n */\r\nexport function resolveTransition(\r\n input: TransitionPreset | CustomTransition | false,\r\n reducedMotion: boolean = false\r\n): ResolvedTransition | null {\r\n // Disabled\r\n if (input === false) {\r\n return null;\r\n }\r\n\r\n // Get base transition\r\n const base = typeof input === 'string'\r\n ? getPresetTransition(input)\r\n : normalizeCustomTransition(input);\r\n\r\n if (!base) {\r\n return null;\r\n }\r\n\r\n // Apply reduced motion if needed\r\n if (reducedMotion) {\r\n return applyReducedMotion(base);\r\n }\r\n\r\n return base;\r\n}\r\n\r\n/**\r\n * Get a built-in preset transition by name\r\n * Returns null for unknown presets (they'll be loaded from presets module)\r\n */\r\nfunction getPresetTransition(name: TransitionPreset): ResolvedTransition | null {\r\n // This is a minimal built-in set\r\n // Full presets are in the presets module\r\n switch (name) {\r\n case 'none':\r\n return {\r\n name: 'none',\r\n leave: {\r\n keyframes: [{ opacity: 1 }, { opacity: 1 }],\r\n options: { duration: 0, easing: 'linear', fill: 'both' as FillMode },\r\n },\r\n enter: {\r\n keyframes: [{ opacity: 1 }, { opacity: 1 }],\r\n options: { duration: 0, easing: 'linear', fill: 'both' as FillMode },\r\n },\r\n };\r\n\r\n case 'fade':\r\n return {\r\n name: 'fade',\r\n leave: {\r\n keyframes: [{ opacity: 1 }, { opacity: 0 }],\r\n options: { duration: 150, easing: 'ease-out', fill: 'both' as FillMode },\r\n },\r\n enter: {\r\n keyframes: [{ opacity: 0 }, { opacity: 1 }],\r\n options: { duration: 150, easing: 'ease-in', fill: 'both' as FillMode },\r\n },\r\n };\r\n\r\n default:\r\n // Will be loaded from presets module\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Normalize a custom transition to resolved format\r\n */\r\nfunction normalizeCustomTransition(custom: CustomTransition): ResolvedTransition {\r\n const name = custom.name || 'custom';\r\n\r\n // Parse duration\r\n const leaveDuration = typeof custom.duration === 'number'\r\n ? custom.duration\r\n : custom.duration?.leave ?? DEFAULT_DURATION;\r\n const enterDuration = typeof custom.duration === 'number'\r\n ? custom.duration\r\n : custom.duration?.enter ?? DEFAULT_DURATION;\r\n\r\n // Parse easing\r\n const leaveEasing = typeof custom.easing === 'string'\r\n ? custom.easing\r\n : custom.easing?.leave ?? DEFAULT_EASING;\r\n const enterEasing = typeof custom.easing === 'string'\r\n ? custom.easing\r\n : custom.easing?.enter ?? DEFAULT_EASING;\r\n\r\n // Parse delay\r\n const leaveDelay = typeof custom.delay === 'number'\r\n ? custom.delay\r\n : custom.delay?.leave ?? 0;\r\n const enterDelay = typeof custom.delay === 'number'\r\n ? custom.delay\r\n : custom.delay?.enter ?? 0;\r\n\r\n const fill = custom.fill ?? 'both';\r\n\r\n return {\r\n name,\r\n leave: {\r\n keyframes: custom.leave\r\n ? [convertToKeyframe(custom.leave.from), convertToKeyframe(custom.leave.to)]\r\n : [{ opacity: 1 }, { opacity: 0 }],\r\n options: {\r\n duration: leaveDuration,\r\n easing: leaveEasing,\r\n delay: leaveDelay,\r\n fill,\r\n },\r\n },\r\n enter: {\r\n keyframes: custom.enter\r\n ? [convertToKeyframe(custom.enter.from), convertToKeyframe(custom.enter.to)]\r\n : [{ opacity: 0 }, { opacity: 1 }],\r\n options: {\r\n duration: enterDuration,\r\n easing: enterEasing,\r\n delay: enterDelay,\r\n fill,\r\n },\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Apply reduced motion to a transition (near-instant)\r\n */\r\nfunction applyReducedMotion(transition: ResolvedTransition): ResolvedTransition {\r\n return {\r\n ...transition,\r\n name: `${transition.name}-reduced`,\r\n leave: {\r\n ...transition.leave,\r\n options: {\r\n ...transition.leave.options,\r\n duration: REDUCED_MOTION_DURATION,\r\n },\r\n },\r\n enter: {\r\n ...transition.enter,\r\n options: {\r\n ...transition.enter.options,\r\n duration: REDUCED_MOTION_DURATION,\r\n },\r\n },\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// REDUCED MOTION DETECTION\r\n// =============================================================================\r\n\r\n/**\r\n * Check if user prefers reduced motion\r\n */\r\nexport function prefersReducedMotion(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\r\n}\r\n\r\n/**\r\n * Subscribe to reduced motion preference changes\r\n */\r\nexport function onReducedMotionChange(\r\n callback: (prefersReduced: boolean) => void\r\n): () => void {\r\n if (typeof window === 'undefined') {\r\n return () => { };\r\n }\r\n\r\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\r\n\r\n const handler = (event: MediaQueryListEvent) => {\r\n callback(event.matches);\r\n };\r\n\r\n mediaQuery.addEventListener('change', handler);\r\n\r\n return () => {\r\n mediaQuery.removeEventListener('change', handler);\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// UTILITY FUNCTIONS\r\n// =============================================================================\r\n\r\n/**\r\n * Cancel all running animations on an element\r\n */\r\nexport function cancelAnimations(element: Element): void {\r\n element.getAnimations().forEach((anim) => anim.cancel());\r\n}\r\n\r\n/**\r\n * Wait for all animations on an element to complete\r\n */\r\nexport async function waitForAnimations(element: Element): Promise<void> {\r\n const animations = element.getAnimations();\r\n await Promise.all(animations.map((anim) => anim.finished));\r\n}\r\n\r\n/**\r\n * FLIP animation helper (First, Last, Invert, Play)\r\n * Useful for shared element transitions\r\n */\r\nexport function flip(\r\n element: HTMLElement,\r\n callback: () => void | Promise<void>,\r\n options: AnimationOptions = {}\r\n): AnimationHandle {\r\n // FIRST: Get initial position\r\n const first = element.getBoundingClientRect();\r\n\r\n // Execute the callback (DOM changes)\r\n const result = callback();\r\n\r\n // LAST: Get final position\r\n const last = element.getBoundingClientRect();\r\n\r\n // INVERT: Calculate the difference\r\n const deltaX = first.left - last.left;\r\n const deltaY = first.top - last.top;\r\n const deltaW = first.width / last.width;\r\n const deltaH = first.height / last.height;\r\n\r\n // PLAY: Animate from inverted position to final\r\n return animate(element, {\r\n from: {\r\n transform: `translate(${deltaX}px, ${deltaY}px) scale(${deltaW}, ${deltaH})`,\r\n },\r\n to: {\r\n transform: 'translate(0, 0) scale(1, 1)',\r\n },\r\n }, {\r\n duration: options.duration ?? 300,\r\n easing: options.easing ?? 'cubic-bezier(0.2, 0, 0.2, 1)',\r\n ...options,\r\n });\r\n}\r\n"]}
|