From c592678d0c0ce6ff0d4d9ef5bf44214891a4d781 Mon Sep 17 00:00:00 2001 From: Lam Date: Mon, 27 Apr 2026 15:57:07 +0800 Subject: [PATCH 1/7] add AI context --- .cursor/rules/react-native-free-canvas.mdc | 30 +++++++ .cursor/skills/run-expo-example/SKILL.md | 32 +++++++ .github/workflows/verify-pack.yml | 29 +++++++ .pack/react-native-free-canvas-2.0.0.tgz | Bin 0 -> 27759 bytes .pack/react-native-free-canvas.tgz | Bin 0 -> 27759 bytes docs/PROJECT_OVERVIEW.md | 81 ++++++++++++++++++ expo-example/babel.config.js | 9 ++ .../commonjs/lib/commonjs/canvas-context.d.ts | 5 ++ .../lib/commonjs/canvas-context.d.ts.map | 1 + .../commonjs/lib/commonjs/drawing-canvas.d.ts | 4 + .../lib/commonjs/drawing-canvas.d.ts.map | 1 + .../commonjs/lib/commonjs/drawn-canvas.d.ts | 4 + .../lib/commonjs/drawn-canvas.d.ts.map | 1 + .../commonjs/lib/commonjs/index.d.ts | 4 + .../commonjs/lib/commonjs/index.d.ts.map | 1 + .../commonjs/lib/commonjs/styles.d.ts | 20 +++++ .../commonjs/lib/commonjs/styles.d.ts.map | 1 + .../commonjs/lib/commonjs/types.d.ts | 2 + .../commonjs/lib/commonjs/types.d.ts.map | 1 + .../commonjs/lib/commonjs/utils.d.ts | 5 ++ .../commonjs/lib/commonjs/utils.d.ts.map | 1 + .../commonjs/lib/module/canvas-context.d.ts | 3 + .../lib/module/canvas-context.d.ts.map | 1 + .../commonjs/lib/module/drawing-canvas.d.ts | 4 + .../lib/module/drawing-canvas.d.ts.map | 1 + .../commonjs/lib/module/drawn-canvas.d.ts | 4 + .../commonjs/lib/module/drawn-canvas.d.ts.map | 1 + lib/typescript/commonjs/lib/module/index.d.ts | 4 + .../commonjs/lib/module/index.d.ts.map | 1 + .../commonjs/lib/module/styles.d.ts | 19 ++++ .../commonjs/lib/module/styles.d.ts.map | 1 + lib/typescript/commonjs/lib/module/types.d.ts | 2 + .../commonjs/lib/module/types.d.ts.map | 1 + lib/typescript/commonjs/lib/module/utils.d.ts | 4 + .../commonjs/lib/module/utils.d.ts.map | 1 + .../module/lib/commonjs/canvas-context.d.ts | 5 ++ .../lib/commonjs/canvas-context.d.ts.map | 1 + .../module/lib/commonjs/drawing-canvas.d.ts | 4 + .../lib/commonjs/drawing-canvas.d.ts.map | 1 + .../module/lib/commonjs/drawn-canvas.d.ts | 4 + .../module/lib/commonjs/drawn-canvas.d.ts.map | 1 + lib/typescript/module/lib/commonjs/index.d.ts | 4 + .../module/lib/commonjs/index.d.ts.map | 1 + .../module/lib/commonjs/styles.d.ts | 20 +++++ .../module/lib/commonjs/styles.d.ts.map | 1 + lib/typescript/module/lib/commonjs/types.d.ts | 2 + .../module/lib/commonjs/types.d.ts.map | 1 + lib/typescript/module/lib/commonjs/utils.d.ts | 5 ++ .../module/lib/commonjs/utils.d.ts.map | 1 + .../module/lib/module/canvas-context.d.ts | 3 + .../module/lib/module/canvas-context.d.ts.map | 1 + .../module/lib/module/drawing-canvas.d.ts | 4 + .../module/lib/module/drawing-canvas.d.ts.map | 1 + .../module/lib/module/drawn-canvas.d.ts | 4 + .../module/lib/module/drawn-canvas.d.ts.map | 1 + lib/typescript/module/lib/module/index.d.ts | 4 + .../module/lib/module/index.d.ts.map | 1 + lib/typescript/module/lib/module/styles.d.ts | 19 ++++ .../module/lib/module/styles.d.ts.map | 1 + lib/typescript/module/lib/module/types.d.ts | 2 + .../module/lib/module/types.d.ts.map | 1 + lib/typescript/module/lib/module/utils.d.ts | 4 + .../module/lib/module/utils.d.ts.map | 1 + scripts/sync-example-pack.cjs | 40 +++++++++ 64 files changed, 417 insertions(+) create mode 100644 .cursor/rules/react-native-free-canvas.mdc create mode 100644 .cursor/skills/run-expo-example/SKILL.md create mode 100644 .github/workflows/verify-pack.yml create mode 100644 .pack/react-native-free-canvas-2.0.0.tgz create mode 100644 .pack/react-native-free-canvas.tgz create mode 100644 docs/PROJECT_OVERVIEW.md create mode 100644 expo-example/babel.config.js create mode 100644 lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/index.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/index.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/styles.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/styles.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/types.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/types.d.ts.map create mode 100644 lib/typescript/commonjs/lib/commonjs/utils.d.ts create mode 100644 lib/typescript/commonjs/lib/commonjs/utils.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/canvas-context.d.ts create mode 100644 lib/typescript/commonjs/lib/module/canvas-context.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/drawing-canvas.d.ts create mode 100644 lib/typescript/commonjs/lib/module/drawing-canvas.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/drawn-canvas.d.ts create mode 100644 lib/typescript/commonjs/lib/module/drawn-canvas.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/index.d.ts create mode 100644 lib/typescript/commonjs/lib/module/index.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/styles.d.ts create mode 100644 lib/typescript/commonjs/lib/module/styles.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/types.d.ts create mode 100644 lib/typescript/commonjs/lib/module/types.d.ts.map create mode 100644 lib/typescript/commonjs/lib/module/utils.d.ts create mode 100644 lib/typescript/commonjs/lib/module/utils.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/canvas-context.d.ts create mode 100644 lib/typescript/module/lib/commonjs/canvas-context.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/drawing-canvas.d.ts create mode 100644 lib/typescript/module/lib/commonjs/drawing-canvas.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/drawn-canvas.d.ts create mode 100644 lib/typescript/module/lib/commonjs/drawn-canvas.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/index.d.ts create mode 100644 lib/typescript/module/lib/commonjs/index.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/styles.d.ts create mode 100644 lib/typescript/module/lib/commonjs/styles.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/types.d.ts create mode 100644 lib/typescript/module/lib/commonjs/types.d.ts.map create mode 100644 lib/typescript/module/lib/commonjs/utils.d.ts create mode 100644 lib/typescript/module/lib/commonjs/utils.d.ts.map create mode 100644 lib/typescript/module/lib/module/canvas-context.d.ts create mode 100644 lib/typescript/module/lib/module/canvas-context.d.ts.map create mode 100644 lib/typescript/module/lib/module/drawing-canvas.d.ts create mode 100644 lib/typescript/module/lib/module/drawing-canvas.d.ts.map create mode 100644 lib/typescript/module/lib/module/drawn-canvas.d.ts create mode 100644 lib/typescript/module/lib/module/drawn-canvas.d.ts.map create mode 100644 lib/typescript/module/lib/module/index.d.ts create mode 100644 lib/typescript/module/lib/module/index.d.ts.map create mode 100644 lib/typescript/module/lib/module/styles.d.ts create mode 100644 lib/typescript/module/lib/module/styles.d.ts.map create mode 100644 lib/typescript/module/lib/module/types.d.ts create mode 100644 lib/typescript/module/lib/module/types.d.ts.map create mode 100644 lib/typescript/module/lib/module/utils.d.ts create mode 100644 lib/typescript/module/lib/module/utils.d.ts.map create mode 100644 scripts/sync-example-pack.cjs diff --git a/.cursor/rules/react-native-free-canvas.mdc b/.cursor/rules/react-native-free-canvas.mdc new file mode 100644 index 0000000..33d6b25 --- /dev/null +++ b/.cursor/rules/react-native-free-canvas.mdc @@ -0,0 +1,30 @@ +--- +description: Conventions for react-native-free-canvas library (Skia, Reanimated, gestures) +globs: src/**/*.{ts,tsx} +alwaysApply: false +--- + +# react-native-free-canvas + +## Stack + +- Skia (`@shopify/react-native-skia`) for `Canvas` / `Path` / snapshots. +- Reanimated shared values and worklets; `react-native-gesture-handler` for pan/pinch. +- Use `scheduleOnRN` from `react-native-worklets` when calling React state setters from gesture/worklet code or animated reactions (not `runOnJS`, which is deprecated). See `drawing-canvas.tsx` and `index.tsx`. + +## Style (match repo) + +- Prettier: single quotes, trailing commas, avoid arrow parens when single arg. +- Prefer `StyleSheet` from `styles.ts` over new inline style objects on hot paths (README calls this out for `flex: 1`). +- Components: `forwardRef` + `memo` for canvas pieces; co-locate prop types in `types.ts` for public API. +- Use `import type` for type-only imports. +- Mark UI-thread callbacks with `'worklet'` where required. + +## Architecture + +- Do not edit `lib/` — run `yarn build` after changing `src/`. +- Two layers: `DrawingCanvas` (live stroke + gestures) over `DrawnCanvas` (committed paths). Context in `canvas-context.ts`; path completion sync uses `promises-delivery`. + +## Types / API + +- Extend `FreeCanvasProps` / `FreeCanvasRef` in `types.ts` when adding props or ref methods; export types from `index.tsx` as today. diff --git a/.cursor/skills/run-expo-example/SKILL.md b/.cursor/skills/run-expo-example/SKILL.md new file mode 100644 index 0000000..850492a --- /dev/null +++ b/.cursor/skills/run-expo-example/SKILL.md @@ -0,0 +1,32 @@ +--- +name: run-expo-example +description: >- + Test react-native-free-canvas via the Expo example: sync packed tarball then + start Metro. Use when verifying consumer install behavior or after library changes. +--- + +# Run Expo example (test the library) + +## Why not `file:..`? + +Symlinking the repo root (`file:..`) makes Metro resolve **Reanimated / Skia** from the **library’s** `node_modules`, which duplicates native modules vs Expo Go. The example uses **`file:../.pack/react-native-free-canvas.tgz`** instead (same as a real **`npm install`**). + +## Commands (repository root) + +```bash +yarn example:sync # yarn build + npm pack → .pack/react-native-free-canvas.tgz + yarn install in expo-example +yarn test:expo # sync + EXPO_OFFLINE=1 + expo start +yarn expo:start # start only (sync first if you changed the library) +``` + +`.pack/` is gitignored. Run **`yarn example:sync`** after clone or whenever `src/` / `lib/` changes. + +## Outside this repo (simplest mental model) + +From the library root: `yarn build && npm pack`, then in **any** Expo app: `yarn add file:/path/to/react-native-free-canvas-.tgz`. No monorepo, no `expo-example` folder required. + +## Notes + +- Expo must be started from **`expo-example/`** (`yarn --cwd expo-example start` or root `yarn expo:start`). +- If Expo Go / simulator issues: see README (`EXPO_OFFLINE`, online start, Expo Go install). +- After Babel or dependency changes: `npx expo start --clear` from `expo-example/`. diff --git a/.github/workflows/verify-pack.yml b/.github/workflows/verify-pack.yml new file mode 100644 index 0000000..e2a3488 --- /dev/null +++ b/.github/workflows/verify-pack.yml @@ -0,0 +1,29 @@ +name: Verify pack and example + +on: + push: + branches: [main, master] + pull_request: + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: yarn + cache-dependency-path: | + yarn.lock + expo-example/yarn.lock + + - name: Install root dependencies + run: yarn install --frozen-lockfile + + - name: Sync packed library into expo-example + run: yarn example:sync + + - name: Typecheck example app + run: cd expo-example && npx tsc --noEmit diff --git a/.pack/react-native-free-canvas-2.0.0.tgz b/.pack/react-native-free-canvas-2.0.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d92e536e6f25be81ed2b69f92566ddc290396925 GIT binary patch literal 27759 zcmV)_K!3j)iG&fJYYzmNsc57aKaRZkaTWN z5O&#Cuq8*58IrKp_Zs*0?vvcLYu02NV}_*V)lF=v#$B~{?YRb4^W5s-#qEY+?jD-| zx{pt(R9aqILP^g{rBbD|QbYf$)|N}<^73+N3H_^7E>%{_=wGFOJ-}z^2bTA*QfUU0 zER{+~{QHZ1b{a=$+iqgV$8&RrJGl1jPB%dL<~*vDDobeF>i>1wwF288dXCk{EC22E zExT82y8TykbNkrq+rDqR4zhjJ#U4JpMjg*`0^BN~wudot+o;*Kybdm)z(tmGjRx5B zT?e^mfn__k(?J$$x`XREw~d0X?IYi92bY$Ik>#|I<@;{awgTKjEw?%BV<)fz=&x<} zu#fUV7o*%EtC5>0owTsko3kAR@AxZpX$M_*7$6V(foC_NjRLZrW^dSnG4R(tyKl1| zpgMtuKNq-Y=;HzzX94xymfePbF`3q2c-FK1ZUMDyX!>jz-~#gDApvUv=CSB{$j80j zT+-j#?GQB%a|LwL zINI7fK0+tj!GX4W^bzfCAZ_;}dfV8o7m)d3|G+#vM0*Ewjh+4NhFLG5#;&n_TyN}d zBK`OX?d~0+?Z!^y$gHEIJp>)HrW)oUG`3?N7+c!zk)}7c8%G}ta~qALU1)P-?*M6N zUpqKz7{}Y%0op%4*xx%ek+xe$yL-Eh-Hn6B?xwk8?j99UV;Al2A@jYtdxQ?RwC!!^ zYEC;o+S)sS@gZYx|KmYpbL$9g?QPf1gF~d7XuF~5+a~R5_aid4wZ={X)wLaM(;7C+GX&jmbq#ZO40U#R( zdpm_W0O#HY6lv^2y6Il>jd~JD1P8s|gQ1{B3A^IG-aAa`S6*P1o@QWRRU_(2a-I z(c<%efBCY1d|-b0@_aF0DzFxcO%GcEX65Gd&al^;XI;pi<6{Xmzc#nH_;2L9L$8T< ztiix`I>!gw>#@yW>|29>1pfEQ!p<7|$Krowc{z&zOUva-hX0R%|8^fx2K_)G1VcBd z?YVvQj3D2$iI6qa07p=Yk%%K?hK^73{BL;{NDd1W_V;`Km#gKKYW)1KWcdHvp8va6 zU|-gVR?<9#1s%dz`Js}SWyc*mY7lADh(FOl9)>|U#Bd98eusY&Q~6Z^r?!&{cq z>R~Un^A0Vx(52;a2`#176=jO3B1F;Xk1FbwRTuXb5nB#%g;_~1@l@4SZtKXrna ztbnNe)xSCzI)UAfPi*n4f3@Jzmr%Yvbcp%}ed*vJvId6L?BYD0M?a9=M)@2sn?wI+ z9R=3|?6%Pfw$68~!94PCF!US*XVV&jQNV&Y_>z~%gE}etXpL9Pr*)6kkr*N!3af$9 zYZRbW+1-kpFdH~ zB{;1@fV7YZ8`;(meoC(*jBY4=$Tms?x;IaI51{d&*tPsTo)^sp#SRY0oS`8Ht)n04 z%a?)Y2JV+Ht7Hw(O#uN#NTfl~D0|Vt!QQ3AU(~VR^z1?4dTXfddMFR=4?#bL=jk3` z^MGltqaif(;|7MOG*WC@y&iyiI1jLfCTz5hEcAL@r?e7UWxL3R=JPfb2iV(19|!ZY zl?YvR3TRkBHmUw;_!&f&Ps7h^=tgW!g^q#(m4em>NEVPYUqH^NJ;YHwyaywj2faoZ zt;Ux7hVgiH$_h|UZG=G9cD+l>YaQVBd_E5c!@vrL17NT%HWRY4xJYK@&nI3 z$A;T;J^Ay*ZUtTV`Q3H<)>)6>k=64tJaZiwi0QQEZVJf5?Rm8Rikv@ml+f8>*Ya@d zz12hONDeGY?~6kpi;_b;pN}3%Me=9g3cAG|>m28S1oCct`#YYp8yG7>moUdwR4R~P zT@32iRaBZo=tk)V0AM?vDSIL?Q(9|b&%VH|{ab;kPAjn{^90->AQ#EOUku#C_nU`- zXFDCBmY+T=9XG|%qwJHRFQxYI5yiK<+CtZII+$(2cso|FcV;!u=kv`TwmiNg5byXk zAPTDtvuDL#Q)08q3Wv7eD(!+EZ5U5m18u5`YAc4Yxn&;Q-fh&%VIkbu@g-USvu-_jezdxW?VM4}Gnb4+C zz2tI~YR!u!rYpx5X0l0zQS`8B^{^OyLG%ybe0Vo60I^{^R?q&9r-Lb>jI^x+`otG1 zv@tAaR@=gI^7C^DEiR%02+jR&wD8D~OW~wd&bf0uY+rHT! z1lRfbyRIQy1}v5UPXhih-j3d@6dY|{cz*i*3U8(c#&r9IAmyz#96z-RVl3zQI>JUc z$BzANh~MJt`TR4O(X$Be@mPGzh)PK;&3tG}j9_XC0#gbo0$~oXFq7FIxIS)4vONKD zKD7J8USK)c9r}4m^9v!yfONukbX@9@`ikOL|0*m-B==g!0d58`LAu&Z$Fmxp0tIuk zYxi0nc2;lMck#WAFAEB9d)>pUTyw@*>>@pa_<~N}m!BXnQPHrVuzap_Xn)76VeX-z zuzKxP_#>aBjI!OsS7ljB4)fFPU?Lf5zE=!0Z#V|JG_tnf>Q6?Z2F=Q?f~HHQWfCZm4;-#v5Rk8d4!- zjaidjMAS?L6xL*gjm~kijO^?H3KY-}B$bfhoY{9tlUxBpe^4fqdH#9*T~1P5|rC0QtJNasL{n`4w#RnD-0!WkJ3 zqg60&mU`Ln4j(VmB$j^|{i_OrOy`=Sb7l0GO)gWW{_e`ul=aTEq)$dms1{0NtOo*FEcSr<-{OnYN ztnUdmf@BVv!Y@VP7jeQ4K@OzmOr@9ke_NN%1L^-tp!kdH|5jEq{a@z){d@R-&(sq; zbCk{;r87tAr|Br|+}=$Zw1iTkz9t8l*drNit^_h6bgg`6h^Ar^f5ovb zwDpC^O{LH%J)m+PBd`UPuq5uZzBLfmi95T~q{z%v;3nn__>-vYA#W3;mzW$qv7?M~1dI@xohKzSr}%%&Q2HAu|5YosSpJWt%2MY4@r3+8 zfS~u;<7zgr5GDeMNfNt=>pC75i)N!Ejzgmi1lv#l?E0AIZ;=-oDZrHFf ztmjSTMQ&2|;BVLM@7S;;rD84VoppuQQH8(R@G!o;S%^^HLQMP*3;bbaKtx=LL`$G` z^z5u>HP4?#;wI2KDwovY3I6>6eA>`D`V^jbAu`v`p&$$TLwIn~pTs9wdDC{i{+?%d zY{wvubIF>DPg0gDAQmye^_K)BSuZ6;Mf?H}UeGvazz#4tKS^TgD?Pn_sK?qs2w!TNhY% zg8rZbrwk<_O~iK@JFWPLOs91pgHqr(eGf4Z!fxM&zzzp{esp_4b+R3PFdazvm951_8%u1OvO4PlhyY+oW=GyOG)5Y4lMb zg?bFH@wRpC4ud3Dt}c#*9wS7;zd!J((59v%4ZwxoPsvJV@km$?w2(8x|mnu zauPa?0A|+njxJg<3`Qe|#=a9njO{vnhsTc)y59;&5T#K8BAiEu(w?UpnmH~pTGEsCLhDt(sU%b(Nsj#_gv8b|g;>k!!gv1by8A}P&5n2+H8 zD*7ZXPHY2zSWQLE;uTlu$7+2XQR_Ndi_Bv+ahubkp9|q}Qjn}BZ-HXdb(&U?|5W-+ zBN@~%L(jdiTiAva>qQSfBBO9XT z=JTJfNDS|5v~Y!15x|!JzDBF)`m-7{)Easu)^HV7N~K7YG+Q?wp|^_iV-_b-d=c@5 zuzS@Q?hC6|ydq(~X^6TODtkSu>~%co+v>%`zEgGy-$#j?NA7=dKC&%4DL5vF#TEK9 z1&XO4xgJwxBFL~gCfVj!g(8Uu4614i{;nW3Dk`xbIxTk;Kj#N{0QwmPl7Ok?@hgR5 z6nog|1l?#Hr;O1S(VU~mn-3S(!B`f`KrsS5;53dk2ah;g81)tqlm`c+W~9s{JQl`h zMj2p;*mSIc-*qQ#mW`DwV>r9}y4bhQaiec_FmF)vubpN-v0JFUPoXn1ovxoY9r7}< z>A)S=aN2B0z0vRwT;1~V^3sUbEtoaRxBEdPS02$(5ddwtUf&9e`@5S3^lfPM>;N$7 zMJeVSTx!Jf|KSBkMH=%>#)=lP({x+-h|LHFEJh;$tMnJ!hH&nTf-`tlbBOl-`Ih-C6T=*e`;6J< zTY#DW6(0OP(pL&=$X%LF&dSMt9=L80?)vswDQ_9opkNnoIywR|hEK_ZP^HDs$&uod zq{>um`n-eiD43HUKT`{#SJLjZ8nIT%kF;B@Mr>F~?HGyvcj3~~_LUe7Pf=~cxeGUh zv9pg&ev*j^^L#1IfEyVzLL(3fh z9yI=A#@>J9@_#N@;jYK9|6gTgIlKS$5#v8@kx?_s*O7;+xl82QBwu)J1~I*-XWvxh z5Y{C#oZl)6WuoMpT#H(uAt_PSbOA**t0$Cms`c`-q~c z9zH5*N%7@LD-!qGi9}M3_soe@80&qL7^?LU9yYh>INgh8+;kH>W$20VTX@GrW`AoB zm{|R(yj+q;G18MIa-L`2E3@%lQPTw9yT^*!*#mj0+;zMbEN+G5Dp;`ei{2m$Yjx>G2J$bGm>D9umm z7LlMc&s-s%h${q1%@R^h-__$`OgjAu(&*`BtIdQ50^4VxE_RBy|u>ynSo+V z_zfKk#1w@IB=aAb#D8GyJp`GDz$4}V5%$0bu>Y4z%geF*KdZGY|KsnT|9@;Io>8tv zA)i5V8Xa~q4vI|=gS`(%Mh+}~n;`sHMddjr7lMh|vK{P2-cwQ+J20O8yWMU-6O{=` z;xz}ZZ&P){GwaNEd&2-f;|$k8aGE{b4#W?SWm9Cmxk2FenFWo&Fp<;=oSZGKOYr}h zG4_we|D}~`4F4+xl`{N)wEV9Ur_$VKBFA@zgul=E57~|U2g?5k9)RU|{=Zu0|MyFt z|A}bB_fy8E{|f%UGsgb0_+Lsm|4ZdshX0R%|Ljozag$;4KUn@B26pek&j0etawXyX z&+h;GrRD$dRlAA|uigTzJZ{^)p0J_K=E^{6r3?*3u~df*+|rgz@47yk1jzXM6|Y03ONdXCDJ8q601cf-EIt^7O` zt6KpsI_@R?HA$t@$d(GtO8uE~Y;%GhKeiM2zZp~ivGl)MN#g%9{m-N7e-t#GEaZxD zj*m-pN72%eq;nLd97z~M(|&675&e!-@RkHF``n)YXAg^Ceb;#a`MZk6G0WXV?g!3YV9$s9?^aQ+QY;lq^l6J78SIUQx^}0#Fu)!} z0$ENIBbEmWSxyW2=QwDRd#QW&nP)*lC)cCt#t^kd70}tx?ghwoP`bXErrbh)-*tm7 z33?!{4=hLAB?!@MHuj5jlyr=KjynwIppzC1_{=>+^au3>%;75w!bMjhb`J_TZVMw; ze-R!ouo4S^GsWgtU)CJBtG43@R<8#&uPx6(3k%K57BO@3dWaWMtHCY|ppyAvfA7oQ z#>RGI*IX~7v^Hq@SPQGJ)3Y5ss`q$J+x2hJGn7_qTTaV!?baGl^}?(nRKdscsOG_h;pi#i@)r-hxSjg>|F zFZO%3L%=ey$fW;QE|!aBzVH64w!3&{o#EcXfP^+e*;4UEC9N!N7}DRh?asKueH?i1 zgk>e@(krBUQV?=qEtX57ENO4?EB5L1D=&++V!0A|O)qd>MY;0JVx<_VOb5dt$>u%i z4LcNvUKFb%D-0~p$6l-?eG89Y7GKJ#g}@3+5d=1^{lAyRa@A$RXSC!}saRf0EE>JQnruXMDbjA- zUPU>WWi7FsxLKR@UX!iKeFm>;#aeMmQvU(QUJ5-Ji8-&fi94}CBS11gRV*o6FP=PgMUO;^!g>dV%el#NlF${;yK0MdbfVWu=zM{|}`96JmX} zK*$-`0^;kOD=_j7`6qI#Iq}=it$xZCi;LpFwB7R6&wVZsRRdJ{T*&pQ`;MPm&8@9z z+MZT8uWMT0%-v*Y`K0il$y-xm{{;A7iQ)fJIkW%$qWGV@TSj8Prfq74N?p^2^$hu+ z7XE{hWopEq4F9W3G5jx=Yn2TDe@*;P*fGHf`cthIE6>@gRaXoT{5sJs$s`u+CHH|Kj&QrwRcXm;RLTpYa7#V*dpCziJHstIL`G?-#}Y zCeO$>UZreI zQ-ugmayW9b4b5g4O1rY*hQC|v5A*3a~(|4jOyrASMEQ`Nr$H{q;1G`Fno7Nv4Q6X?w2pQLJnX@uT`Q|l#7*U zoxMwkKd3YQ%Z2`iv|;5ncwLdiVL2PlU(#LZ;`v-5*LJ;2%WECrcCL_<7qrti?0$Ku zEN_7qzsPOxxk8R#BA+Yd#D()@1Mnur-5xMXA1haV0d zuDTemVP$>VPDd@%!k&GBTl?`2>+}up@q+yuxQFjI4+GD3IshrLCx(8iCrcsM>{?C- zGbpmcR<8%w&%)atwmb@JR)ozfe8UNY3#@jl1qB`U#Bd>(Sb*z1M+ShgWBUQw%;y*$ z1YHcp`)J6 zVbHd3_6Gzp+H$1oeJ5li^arkwTXOV=c7NClEC;(o7}{4z;>JN(#{q6q1nh_k&92>R zd1RU1+xU`T%rylSCxtwD3$*5oeMZ4ghehr}CgV|&?u~0Z5+4b%N%W-b!$ME!c$Lh4 zkMg4g@2ZF+rJ*sm$UXVW*STNhMx@v#dk5vV_`A3CT|;%#9Ev8kd9g!UY^P8XP3%UR z-z$9Nul6Ia-W8g%R{8)B@Z3gEHY- zVOf{Z>MPITL7hH^_DuPd4w1}^vfK1KcRVHKPQ(K;giZOiPQSh-wT;lg4rpudXbDsH zdMI0KhqyY%U?tVYKv3hc|q-bt_!L5x;2X5h#qCyyLojYO+zDgooCmU&&T!s)KLJ z<{JEKSC_DFO4uu~*iRghsX*u~)`S9pw_#wtr?8;A*^mPgPxoW9Hst!68j~mK*G)O; zBiYza3>1bO*+;obhM)kX_wB@Xm7!y~j6DTv?<9P*$o6)0x(!caD3ZLBH|0#&$r z6dPP3H|hp2U}#WaOLczTl%x4(0MJcMGmOGFoy+fr6y=q#ii*J0jG&&_c83WK@GbWI6|UxF+6+rdN2=0Jn}V8{bzNmkJW7@{+drjv$n)t5ft1*cB#GYCxIy zGMwi`Hex9H5Dvr(@^?dY!iPn4A)E0fg;so>Hx4zv8!2!HJ<$o>1!N{oc>Wf2D?NQ% z1~Baaasg5po?fSe-Gp&8D7`Y?tnFxq8K^oTX#Y|ti%9`>rOT;7@hhVqDSoXM{~jw| zV$RV}{%;uK0SstYOma)^I`ZvIHecs$8C9K^Hz^n^y0VWO1bYNfzUvKmgauF>{Xhcc zm@hJ2H=(H7l3TSwn-#06?qcX1CRVPOb-5KPx>SR)9RO9<-Vp$Twrg$eon{_sYNJv| zN9OiUGYB)VR~OKGue{#TjE$E}b0&rdvulTyZyQ+7)z*O+ekAXX6a||}G=X8bUkI(7 z@plB+wn3Xwc3_j~J6g@F;-(cdPgE?Pqyy?{`pSEudq#SDy& zE)n(8kYxPphJvUY^f^IP<#~TYmWS3nWoytqRZrw%mQ^|&+FV}^*}_%*_M1yx-bICU zESpISyrPtNVWur{O&_(yCJ@T-qBSKM3L_aR)Ct zRAL04cH0PX6PBhm;c=kv$}LC4;w2rPe+4!pX-q^Cgcd=i^p5EXHwXI2X3uv z1>z}iChzEQ&8~i7!UTav8T))6o4ZV?XG#-eo9qbs&1B!+38w@?54qSW6hY@3i4o<4 zP5Ql~YoWOG`(&HK zh8XhfXJ6lGT3=`GeV__2Q#A==U3iA4W0KVg6c?t+xIt4h+Dtt_^mo+l56X27)&!Re zm~Os6b@OZl<{QC5fNowXK={3PaFX*J6fH6jg%f0BAS~+(UDIBWjxS7Bj?au3C7bZd z;bS7lI+@lt;&RCHS7MzQsfobKZg36FmfrD9z*bl{40I>Hf-ro z(`s~uFJs8YVe1cW@1tmk>+cOz<&_$V>*Tp6K4$ve7a z9=i$%RXcQ|L1M*7WI=`#86;j#v8B{SZOO+UlNR-F`Q931jPNElMp%;IY^U2I9K{Oc zkFZ6QjYJGJ0(}gMk}|>M(2tuUs`Zr38nHrLD0`qX%Kp$*_EyyLaB^=9URB|uUH!I3 zhWF!)43-2;Bi+VuuGknHC2GnwRdf>;h7ZXWhMx5OGxntk!BtMw4aJ7Asn`%+)@9XQ zX(jlksN}mFa#8FJX(-rG3sqe2SGXH)^-~Yl$()TxHztmPUTHn81pIqO+uju>B^;zrt%{ozI;IE2kiXT>u zKkNA4^!$&`J>-8Y$M1hBl{5YSqsIR_GsynoOcwpGX;>@#scRKuGYdC;g7~l41)clI z|4~iI{{iJQ{QvdvKWVRwx%=gvR`|97$PZ~iUV`YIS#q#JN8j+njSZ-zTR27#LHe{?LZ?c4Yl z`9B{6|DQ(ww^&ZM-!W&Klbo>)LLx+DL3+%AEXLywXh=aQb|5(}BNk4;Vh4E0LVA8R zR&a|~oG`=M(8ppDJCDRb;3^u$5{wLO_f zYd?}l>)lh$qs8)7HL^TfSstz5FppN7?!vv%A)ddH?pANZxfB}0 z<1kRY&bd?EF7fjMZ_hVtrV^jT=5drbQ3*6%$tv*OkWuh2Wat(2E2H3<3r}u;kCPE zgaJaSPR`(iZ7C}6V&FZ=OL;{6JdJ$Tin5K^Szb0 zB(~yK%QmX5llUK)cC|jiv|W==+uZs)>Xo>o8LboP#Hh)wrO}X~9f(*krGMgvEWt7s z?9ha95l_XPL{CNVvDSB0fGYc&wWeu*3tz?yy+&XN@eBvMeZ@z*RoK)HcSA0YoArSR z=VLyOLNRcbl)m87NK9W)t@AUFtj#-(PE>XVskOvWil#;Zf_s^v(J?T@nz&!u*Y@nI5En>j--; z1R079bRYukRq5yO9;BacIOg3bLyX$pC7*$68X*Zvl?M$~IvFkXG^Erctu0*ONojLq zjKtHB5|5+UP0Ua%y!qXzD|aA;rJTMl#hkiiHO=Y89Ho`UC^6@a6lWR_EavPcPBbRw zv}IgTONudWni$hmIecj=>!iprZAFafsA5b{6=U{ggwcB`rnr;KDPPCSDVvI%qD;cO zjhJ$h2-1%!Qp!tRPV0jdLu?~S4tY0L4l&e#I3*qUbaKdcq8!qYa>$V)hYS=s zI!cm5+LMVPW}R$+txU#vO#g4}_iQI9HeIJ}ccydy80Y^{UWwoTSYFBeKOfKkBfjVp zI)H>LW;Z_n>i%D|!2T)lzr3h@${9RA1hzgEiSYUcm> zc=#{Zd5XXfS~2GCG9=`(q zgFpY&h(8(rFID3Ff3=e3fB&`cUv88MBR<}OW-u0-VYNl%##kutsS4pnSThL6Q@-&s~X*?z(!~ewi@B2Fc6Zrp9Z6)LXGyXsO zJOTW_EB8MY|6i$O{C~#(XP-yL|5ZzKy9R5^a#}rduh=Bv z=dF;7@RwHPGPih$`M`7gwvToc=j?*K_M?|E@qtPER?7SuCrc9H~<8RmP?+^!J z^??Om#v2~S$X8cXEwX+PW%Q>_JFn+y9W;{N>6qIlLOfz{pyk))ob`-zVYNrI<*A9 z7cTUWdw7eNrqfd2lU5?n0zPkWl*118d@)@5r8)FG?693EpvOzo#{`VwM-g}`FNZ$f zwyxb_AeNas$m6~px(hFS>m$64UePCN$ew6DjgbrzQ~=Z}c9-M8!xy}z)*;)MN=^Pq z07wO_dNm*ZsFo6gXu3|5`tW=1h26rQSXy>nW%M#b`HvsIkI=(D|4JIXw1e)E-KRG& zwuYX?Ca7EqC~r@s3m?8?FeR#B=(Na%gaHQn)5A`O1_Si$CRQ$CgiA6VYv6a?fJ70T z<3``=VE#<=ubn2_;2c8&SANqiA1^P#aQjf7)ZK8sKAGD7?q;r#`!=+CHX%vA>neKH;(Iuxpn{s4RA0HBmV5lIq|X^7*?7k)`&O7__@hJz~Dy`teW2Y6rhLL5E( zQbit`63_X-E<2qttRloZkIMOwn3O@Je>m2ZfL@;8Ae^wlq_86oxC|LaECI%`Y>l=c3LMDB z4(}^NMq9~{fyZUY_^RZ3z*A<(XvLa%Dj71`YJQ8P3>o{9q-?~xh^(_Em(fw6c9@VM z!(=ySo+!7P(vULPiX^9oP+6EBkM|;hSDP&5$|kwgR*${nwXXOp5|fdbDWj@f#%hS5 zuWcjcT2|#Nxq*nr%8{TD(lZI}Flhjee99xhAb^BKo0udzEPQ?B-*f`X4YfS3t7d$p zmuG>BCUhSx?{0shOJG^BiV~(LqPNss7MR`c)C@N%d|%QL`>;e$yitT+*s$ zENupm*^dQNy@={1U$fAz(CSHLS@e@Bua}A?CW&0KCVqYsF@i?VjBOy=V^S+n;mTm$ zo|6DZHNQwGBMJmOg?naq;mSMT;&{u*syip9*rdwy927c)V;Ay$@oNZx0xK; zdu29%Q)CpOgYw2qy7ogobcY;N|DaU=K!+BuepTnyfg>v^)&CaNjYZ=ryo$y0AoF8VOZ>a%`4SAPkS&z(!-0WE&hOV^Sl;ywcktsm=D?<)Ea{cF(9vL#d z-*sSywwqDkP_OyssYCY-UK#FI*5%qj3%a<|j}b&M0QFK~8jrde$=_oTj60DVl;oW{ zWWz#%DsPBN=i} z=MXuv~#S%~Le!8Z5-u`4YOyK-u~a>R;3WIJ;6 zWIYte%PwR-kqvIkp%{S?LF422q#Y$#+!9kR>#TF-dT4@ae1*R1Q5c*_tBobG@P2t3JW-fEN~negqj8!%y2^&37{v_DID#l& zQ{l+2k}!nCE|YUzjIV5vnwPq)`aP}c`^2hB`1MzHheBbIdfDg_=+v9is<#qfRr)oY zvN@TUh8}LI85|VIHQ6b`jw})iFAa>F>UHwu#@s7~jlEVVB3IpteehC# ztp|o+$Txk`>!mKbtr>yB1N%n!TG&9|ms|hNga)`fx1wA=Ok>i!MvO+Ae03! zB-!EDTA%BZKkn)B-2R(0brgAd1Km2gPnX{~4ukC}sT%tA#MBE=Y_T4?hTC{)yr|#0 zk(X*CK=2L7ouI+UHpsoZr8tp<*|70Kkwx7zVmnXlnoFHfgkyR3Iff#gguiL>w-!6! zCMqwv>vx*rnEl9|(tn3H)f>4PqU*2G`(7dWfU?4lp&rhzp$c#EI{9}%vo$%)3uOlN zG%`YmLaGjxDF#a2jWjx<)Fqhd)AG?7?`Y=6z=-cdQur*o&XjMJ5L#C5+NRLHGLqRC za(TA`wa~bS=|Ef5Q-G$dv#Bn?VG{hlr@~KZ#z<-Az0%AmP=+^;sU|tOA_|2oJ$!BR z2EXW8918>GPU?{PMR&>Ela&q>9kUu5UhFHLX&M2;EBdE*V9781o zh;pg8sNEtLZU^es^xyM!7M2tC$9Q1Ou?3Dz}bv;6AzJ`Pl zE~&lLFLXtl5>lKv`e;u6x*j4JyBT`Ayf0nJg;Jv0eqX131lMtHk>X#>}&?NAy2l;yhWBsVk96F$_RTk>j~^x|HkWr<3R;kevY64NX(b zWx_s9k#(X{3QB4Agic9Z4ng>2Gp3({-$%;r6@1?f6t>_nd_voGsl>C2psyF*(Z9k!-(i-syv-Fmc@|G#aaVJ#~1;bsb09q zbYb$fHnt?+>(_;x^hU~t+e{q{BGU({BWqA*2{Mmu$O4My>{vZORydD9H9;@xQZ1vI zjO(N5*fF{21Fw1})6&Kc9>aX0B%u>hIv*}^F#I6(MGcM-e7FTu43}t;26fJW8!dxx z3eeZ;TbvU#9aRvODTBL8UfTYa%uDNSNplHF;!G)-y~RPN8D3pVMjf5zVuB`pma7%> z#kTO*3jr z+shkjYU8&wQyG|tcsJ$v_)A+dud>rnY_lH$N|Z45x9D7sBXc1yW1TYDvM%VN2^Hb0 zf_Lm*1+!ZpIo%5dj(aeSleLeU@&21arT3t*LwMYB6sCuq52W;kl8`I(SaDR@T8YvY^$!)ghB@_YNMPbyJ4CC$$8`(s&GyJ$*wJ z9{9W+eM9CX)97~n2*R_G{CI1`{Kz(e-zQ|h!nYlQ6Y$N`*BIq9urRO@J$5Xu@$yDu zTI265)jlje(O|)@J7F2ujKQWn)PJv3WC{6yXYBnu&i}VuSuREWf2*}>E%X0HsT^}~yEdeU+dv)8#LjKsl&#_=wxBq+`G)G*rYgmV zE^TPc(5vnHELuS!PLw;+9Ebq+FZ>=-6-i5f!$7}2sn42nKfzbUXYJ$EK5NI40>4!B za(~vN{%Qv)!{{m&oZ(&k)w<^7P>J}eDZ^>2u4>2AxT=-Ks0`t^bZMvth-1Y|?aghx z)S|vv`b&kt|7oZWWl>)=p(f;)Q%vBYb|@Qslj5Pam@wI)LM2Y3-f7A`f`{Y0(~hJ~ z_fX>Aegaxc?=%%6ox192Hi2i_jx7Hs#WSs2k5AZF2-Zi%EA7o~ywZ%QSDHGL^SbIb zb}&}>c%xm`$GD?~9X5|8!XG92l$|U3Y$vViL1NVt3DK6a zBNM&Rj-~28&||AfckFBKmE#$88!7~VvNwmFF_+KMh+(U$d? zE82?UJ+-W-yP_@X(iP2)xuSj76J60x#<`+3B@f$@2l0_==-r7rqS=Zg+La-F$gYi4 zAF@Hr5v^apbtBF=M>JoL(LyhV)3jF;HNi`*oO`^2i)mL2ShBVEoq5%x zQz!OAX|pHCAujXDi4@j2)*vPKu+OZ5J+Lh5u}`&{b!NW|f0Gd6Oe-4w9wU~tWU_S} z9V$0d*|C__%^Wozt{7e(fi1sV9{FR*=Ad$B;=%O`e7wR3vvjfmcFBO+CoOwA+c zi;rz+U#1bG0aW=BreBvm!SAth5OS*}!=n%)@LAJ$Og6NQ1 zVZr>P!Iy-YC_eStX#8vo%bn9McE!j}2LTLOC$EvAXMunS`L)};_{@`2 zk;}_ozyu5EZDZ_(tsw(+6}SH+6y4z(=r~)$Av{M8CV{aDGm&{cN#99tM=Klkeka%a zB6OGI226Kk0T@tFNz(si$~uHK73u%gg+UN63uq4NKcU2U=njYi#>H?WfX_IN{B-LD z7huCm_Wn~)Y03yWOk4y84^j}^3cU0bWioQ3%ZZPh?&V;fOjX65exc^C_YA7MrGz~4 zgRbf#ZJRmPk*2xxcaJP`YN%IZp5FMWo8nuzo6-?9H8Fr^OX1%AYrxq9{fjowhg?IA zUGyO9T!Av7=*hQMm9KfM!eo?7Vix$E7_aDaFKp2AZH$Kc6f-FgYYUxM=XF)aA|mn1 zI9G-#c+M04?5Q>4@zPWKekp5{)6kXcLr~A;{G;{)T^+-F#J&m4_!R4MUZ;e>6ADWm z=6*0S(i=Vn{8b(RwyDqlFMsF#LT~`h1hOd|U}Z z-D$1aDiN-c-jPa$MYa0$DJr_V%mwNp=ou565d;Txz0Vn(TblyoClfY85(o|VLvVtX z65gCR%H>gqHzX5Aix6(K*18r<2)wCqnj#Z{7s}9!VjjCapWD=YsKmiS<~BX za_gdoQV*zz{={;wCAWiL>M*&j$uZ>B7RV%rBotORCdWa-o4)p?yl*=#rO7&|Cwn1J zHXx#|%kY-CmJq|V_+>C-;hhF`$Q7r)S>CX>Tg1oADTawCjrODiL$Z*K&>z@}3RnGd zGSbCSLVv!MEk_Zr#**GlAW@(xnIYal1M4O6H@hhW#^Bqnb3i?(O3v+Q#QRc=NRJbm znCWq|UqihXKSO4kICd`c`n^D4mm|7JlmjoUN8w9eMF;lYP64v6)K~e0n67uyK@1NrFVgYN9iNF>NG%}+Cq#gjZ#PI4FGBHRyI27|?pl>w-Yb0&rIJZGwj3!Xz0K+*7Z< z8Ch}pSQ?zuLINaQf@DIjxNgDBo1li2d%)r@$B#x8NIeF`pC7LtKLKpX$;|-Z0?!2$ z1Bpi>Ay2V7G?s`T7zEc$$n=r>8ali;##kBNtUM0!{w}I%Yc$J1aTB}gaz68^`65?@OJ7b*5bYab^C_5AKQG*vkkNssZ)5uA)Rd-;<<4aUUIgFj(T{I z5}TU(!f5#hA#vH|{1M^to$dNYqo1tY29+?RiOxT=$~9y;hS=?6Qp&W;Bje0+s9%Ud zi&Ujr;+){=PNCqgmJt6dZPq(nS(gyU(;7+_LHtDq3+q7+T>kJi{Enn06!iwt-&}9{ z!=hKi*fq;4=Ic#*soZ4h=C)38-}=KATj`v_ zZ2ddehg}3)yeZ$F&d9d%1MLdtWx^qjlcfI9{f5>{p;PRl`5*S!3jQw?A8?Qv>B=rQ zou@h~>U<(%ha5_rHda+Mc}t<*W(Swg>ICCp>k$Jv&4%fZKGTuEWwrZ<2;?9$ak(OK zxr`P$L6>QPQ@$e-_wh!Ut1nXV&1+Ceuxn7G814#&@NMu1WHkMwTYpTFM=)rJ9t3aY z<>{n427esr6PUj3?w(#rSQkuO7fd;Dv$a|o6<9yG1n}`szd}K;iZqx`0nL$3faVH{ zOZ&$h2RhFU98n)Doqp(PPc%=BU~v9vQp2#RNON-Sw!lrOek!1`>h;~<*=a;W_+SrG z`MM$1+dk}t`)!?%N%o49wX;WAFE8+Q&(#BJmD6_xbp1ILwyIfc4HJ{g26jF*5Oe@l zhNWNCxP*Z-;L1sc@d-8T+XI#Z?iOlBi=Sg}Z?l~s`*zM&?t*M(&^{%~o(GnHfjV&0 zcG~4=!Wo)zG462W+WG&612mP#$A3Rr-U<)iW*oHyM@ZB9VCmp}`0Yq5{1t3-FNOo{ zAJ!;&xD3%Y`ng^Q=^=1@Lpr8^vMA+#FWXXEYuG!JYAxty+Z1@}U8E%yS+%Hk71+tgNC!CT-Vh zvo!0!silu?5utKmwvuIGpBM*Zi;JUnK3w0sZsP=XbFtFfOnQ)rh&ac4y>X6zLzbHo z>30on*?KmfQ;-)s`I6O4H?m(d>9*=obV*RYu{YziO#+O@acL-!#+l2zT%S9JgCjy} z)Y@x|H7w|xwts(xY%l1shUtvOPXBIC1QfHFy~J`N3RNLwkK*3OeEY*r+3sLDDO;I&p!| zj+JYhmC%adi112_?#c%Stw+a2ut5FehQ<$xe-Lq~BMBPw)IbYW7TS`oqZY6B7F|R& z`iaWF+^^Y6bIkH-1JOfY%>H<9{GQ;o+I)>spDd5<+M)R>+hyA<0>j8&-Ol)QM$pII z3+;71)ejYU(>=x(vb&LVTy#tF)WW&N-gel`v8Lp4GdR^@8KQIDgEteFq{4SdKKqN* z`Brcw30X~uJiOTu>FPS3L+J>1LPWoG39AqTi3!{i*68lDEYf--&kgMFEsvwZ-go|f zQduDpkH?8Lc@b$WL9@G#(0tJy7mcT1tXas9x!;OeWg8jBH7Ab$?jpc(QdxLEU-POL zwwl@z9ewhvvc*`<)@;VzyD?~5e^~f!vs;JjwvZhP=ThasWB}*Rrt?HCl1OY1A#HP6 zA>C}f{j|IH94l^F(zBw*lY7M4CAyyz#CDPb)oP;lg7eZkoLw|4vaDx)T~@-?i!`5Z zmz6)r%Q#(1q`0z&E{=$l|oTnhwsekx64>5Sul(h+! zyF*Vly7oF|BZ{cf@e#J>n}o>xQDK=YVZ2z~+)fj&S(zB)Q?nNfi_262ViJp{0kiM@ zX)3@{;=6eN_(MrK(&%|$<9HC>gL30&_KW)FZ-b~DN8jeO-h43?LCk7gCPj zTO=bRXG83oCMLq%YvY1ACs!AAm!F$5q0w}9sRe|_1bv^s9cn~;hqzOpg=6Ovk8{X* zc?Mnny-0;N1fGm>kC|*dF?E~wT*-~>;0o|3tK2hnf|GUrvU|F*k+mLh;&XcnLt|&Z z`X8@%elIqCWLsptoCRsI3D{g{Bl6Z;O(@fe0enU@*(_r1U%XtjD#F+n#tKKUgp&H*+SpGMKvdr2g_b_YF|c0{ zgDPVpZhM6wzm?DX#nKvw+BlXosoukor@4CkvZt^_=POTLu%*jVzAV`G#yNY%uQ@_2 zIidln)c1$EYgVhZQ3lZ%(GCXjWBBv3xgc%Hle}rhG^thxFA~9T=x9m?|4i(9h~$p2 zPsA7aCRbIH9wl0GEe`@=toz>cpF}}wKIk7@Czvc*e3Qhlj&;zQ$fmd99{A=_(LK}K zB#oBozTTarOX*_?<|EuF%>aDMFkhSyX#@gtal|<-WR^Gmam4fWMpfXw1?na4R$sj{ zoZ_!1d~HPf6NoN~xJtnGA3Wp_!~y-NLVp6wRpbQ(JWI=WZ4tA0x-vDs?(kWP6%Ssb z#I1cGou$jG{5jMZr@ozPr!nlovFy5>;6iOg^r=VQ2}hC({a9>+5IIgEh7!wd^&97* zFXBB%GVbdzw?H*NDyp8=?7-)eIP$aAjce!cM|M>vUcCBp$_8O zcU!%GrTC4O{s%HGYS&_e2w9%gA4tVw00w1!3o^sV2gUMUNn9c(n9&!;%q(lDDd48oy+!}tM~#h-p=ds!z~0K zvAmt&NJ_t?Ftzi+&osizqQ_eZPcm5hECZd$U$*6O`8Cery?SJ%rcfF>jVdMxvv$~w zjOfHx9CN7J2$KbKSJ1oP(~WRcR%ZJ(d1k`^&ifWTz1~Y?NnduUxGNZxV$0S~=ZR>$ zM$_hzXrqkz7kf@-@XrIBtXv81ttrTXm{n%blH9vq7IRltJG|yU=+C4bZiD8^6l$`G zCz|qR>Vl3YP#~gBPLG+o0pS7qxemh3HxbUfW2g`$6VuqppGMJFR1@qU&Z*$NaidO} z_L*K+o&bfqL(XeL2c!x1?JMTZa>ezY^s~BO8^^Be-NoZ(=I@=63#pNW^l|;KGQ2Lo zXjfFc78NOSa685tT{5*Wq*i=>5t@e0*5~~sv03;bkp;DtZgf6R>IWB}1?L;=cMFcWLL5k~OrPlKiQDnp>2@gfpnF3Y@qT*?HVJ;;#3r4lps=6m zx-Ak7`~yl{f?=Pvo~?gOd}K^+ygqLyXQx_(p1wsL2yD&m-7gDD0yEt0k- zFT`I0y?+117_XL$e`*YV080Six%2l8219l59G-})8#mtsUN-|Ja3{-~e@2!9D%?;2 zBhBAVBnJXDiRlMv{SB}8_HK&1KU%(Jbe*oCdJNfPh_o06uZ*6dsxbr$%M52D`~{PG(TsIkexeb4efX3uJ+-3ucny`gAyh z?$ULKc1T2I#m=L2k#s@39aw@7qK5|z&2GhYm1c@w10&{x09tc2Go};4jTWf?dm%ax zc>~0rkvd>SK2yY@SQ-tvTLMq;Ca77N?JG;!WOL#h4Jiyq#g}=(m=&0}ACmCm3gEyG zu^w?g!_1a1Q=9ZOvK!g!Em5d?+ES9UFEAZ2FTW$?i^KCdBy2(nJl5L+1wi5g=qwtD z90Bd@XfOkomnIM|B={0KaC&uLr7^M%R)LMM_A_h&uM5E?+hC2Ci2%<%=f96fkye;E zBcf1UDllBs3{71DF15D7=sPdE7n15_hEgvh!oy1X`iB%os)B$Bl>Ox}XcH9}=%`J& z0O5uMP5q9;PWH{KMLP{R&W|KKn|%4EavU^RKnr~6cc`wup0V0F@cSIdc?Ae6PMPo( ztuk(YPvGE`rD-oy@p5IMC;xtYveS&$ksa#0It6p(+yfy2CPSy7@jJL5YyM&FKO<97 z@-Y;CC(7`Dl9hn~XVq)V%l{0Y1s6cz!GQm`M<9LMyN|D~X~W{6L<$U^s|>U7>FYOyIGEa6auLDU#0NZJ=}W==2g0oIj7|dfF~F& z?o1+g05;CKTBtZ~DWEK+0*Tn)@gG#y!yJx|mvJZ(dv_CN>($Fl&l4}Ep=F*IBTw)G z5~#||AJn%HKLp)HIV6DqaEn(Wd;-k4%ST|;u(d;?)yEhsr`r&VJK7;d;@+Ryodbh}$ zonMw5mFH)=@3wV(3~;r}Bls%(4VTdP+F4k^e`_Jjakz|E0Dak?$V#9ose#ClS~kxy z56FQ}*%k;2i`6K~SO92~fbr@_&%V=zeV|wlig6DVeSpE`$G_QsZCJ5_)H{Fe?lctN zVgQ|w)<~#3Ss<{kTyR&4ZHXef_~qM-;GCDu>EBZOdT-;ou7(bPvlFQLI>0vb-$Y1% zc?}b<1i;9I&UP@kwXZ!P>u*N)8fH(-4b{~%fsE+&`NA~N{-hm?my;d%M^&}O|9y|WI62fqZV6fx5dXy3? zDgk>R#c@$x=bv?DzbERwHBE(}fX+KD$xo^0;GcSPKZhWo-5!Wz< zT!;uv*JyxruD`y*en5kr4lrS#21FTQK=TluXfHtYxCU3k z@nM|o$)())AUKC*L-HQ9OFH+z6&=>xUf0Vjo%?_f!ZLgabFE1K>Q`RX@^61KnX~Xz zse^qWsE|s%qOW@p2iiw0b_i5&9)s)9bdV4mpYHCaG_%LV>{*prszQ6`4m&{=ON*RY zhL*gou6oxM^2k9~q@V4Kb%h^hNc;o*m1MQy%R3Dh5Ui2{OH&N}n>As+t zkb{9JZ4P}~wAvE_t{Q&lC$r^C3<_?SqsAc_=$q|lM#n~rVsbQ20e=Y4`P}q5);|TH zZJa8KTV!iUQ#H5lZ0!_jCpq1IeF#yTaFQ;wMw{EPf*f>Tr@lCpE)H303^K4+_jGpN z|9}iW!eqS=f-2~+m5ATv&R6CqoBLq#({OTsI{~BrMDC0yqI%9y_-B%Z^|6Y9!ab&` z+DFsiIdzz1T4s?>1dUS_dZ)G2Z=++-|LC~v|4Fz1lI_}$0wJ)fb`3V`e{$}>SaaUf zcO^hqZ}|Ts^!`(SS118a!Kd^#AZ81`JC#O(rj&lb3JQ$g0~ja)pO1l)G+?O))?^J$ zT!4L60p6y7sCva?R@AK_v;i|<_5yLrP9J(^kdD#H*KXRO4f(rAR?nOsyW-D_<{uv8 zqn?afm9`F@x~J6#CS%w4&bofDrKGBFZ99z D3>F5C^J-#wadB$9opzoY6#u8$es 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 D3>F5C^J-#wadB$9opzoY6#u8$es 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. + +### File naming + +- `*.tsx` for components with JSX; `*.ts` for context, types, utilities, styles. + +### Styling + +- Shared `StyleSheet.create` in `styles.ts` (`flex1`, `canvas` absolute fill, etc.). + +## Scripts and workflows + +- **Build library**: `yarn build` (runs `bob build`). +- **Try locally (consumer-style)**: from repo root run **`yarn example:sync`**, then **`yarn test:expo`** or `yarn expo:start`. See README for the tarball workflow or for using a separate Expo app + `npm pack` outside this repo. + +## Version notes + +The root `package.json` pins RN 0.82 / Reanimated 4.x / Skia 2.3.x for library development; `expo-example` uses Expo SDK–aligned versions (e.g. RN 0.81, Skia 2.2) and loads the library from the **packed tarball** under `.pack/`. + +## Further reading + +- Root `README.md`: API table, transform order, peer installs, `CornerPathEffect` example. diff --git a/expo-example/babel.config.js b/expo-example/babel.config.js new file mode 100644 index 0000000..be19d58 --- /dev/null +++ b/expo-example/babel.config.js @@ -0,0 +1,9 @@ +/** @type {import('@babel/core').ConfigFunction} */ +module.exports = function (api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + // Reanimated 4's entry re-exports `react-native-worklets/plugin`; must be last. + plugins: ['react-native-reanimated/plugin'], + }; +}; diff --git a/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts b/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts new file mode 100644 index 0000000..ad8276c --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts @@ -0,0 +1,5 @@ +export const __esModule: boolean; +export default CanvasContext; +declare const CanvasContext: _react.Context; +import _react = require("react"); +//# sourceMappingURL=canvas-context.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts.map b/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts.map new file mode 100644 index 0000000..30020f5 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/canvas-context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"canvas-context.d.ts","sourceRoot":"","sources":["../../../../commonjs/canvas-context.js"],"names":[],"mappings":";;AAOA,kDAAmE"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts b/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts new file mode 100644 index 0000000..90ba43c --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +declare const _default: any; +export default _default; +//# sourceMappingURL=drawing-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts.map b/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts.map new file mode 100644 index 0000000..bdcef6d --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/drawing-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawing-canvas.d.ts","sourceRoot":"","sources":["../../../../commonjs/drawing-canvas.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts b/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts new file mode 100644 index 0000000..7b8b4ff --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +export default DrawnCanvas; +declare const DrawnCanvas: any; +//# sourceMappingURL=drawn-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts.map b/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts.map new file mode 100644 index 0000000..50733fe --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/drawn-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawn-canvas.d.ts","sourceRoot":"","sources":["../../../../commonjs/drawn-canvas.js"],"names":[],"mappings":";;AAeA,+BA2CG"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/index.d.ts b/lib/typescript/commonjs/lib/commonjs/index.d.ts new file mode 100644 index 0000000..012e0ad --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/index.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +declare const _default: any; +export default _default; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/index.d.ts.map b/lib/typescript/commonjs/lib/commonjs/index.d.ts.map new file mode 100644 index 0000000..841a279 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../commonjs/index.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/styles.d.ts b/lib/typescript/commonjs/lib/commonjs/styles.d.ts new file mode 100644 index 0000000..def6295 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/styles.d.ts @@ -0,0 +1,20 @@ +export const __esModule: boolean; +declare namespace _default { + namespace flex1 { + let flex: number; + } + namespace container { + let flex_1: number; + export { flex_1 as flex }; + export let backgroundColor: string; + } + namespace canvas { + let position: "absolute"; + let top: number; + let left: number; + let right: number; + let bottom: number; + } +} +export default _default; +//# sourceMappingURL=styles.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/styles.d.ts.map b/lib/typescript/commonjs/lib/commonjs/styles.d.ts.map new file mode 100644 index 0000000..e27c485 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/styles.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../commonjs/styles.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/types.d.ts b/lib/typescript/commonjs/lib/commonjs/types.d.ts new file mode 100644 index 0000000..f89a43d --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/types.d.ts @@ -0,0 +1,2 @@ +export const __esModule: boolean; +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/types.d.ts.map b/lib/typescript/commonjs/lib/commonjs/types.d.ts.map new file mode 100644 index 0000000..9ac3051 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../commonjs/types.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/utils.d.ts b/lib/typescript/commonjs/lib/commonjs/utils.d.ts new file mode 100644 index 0000000..06dd39a --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/utils.d.ts @@ -0,0 +1,5 @@ +export const __esModule: boolean; +export function getSharedValue(val: any): any; +export function fillBase64(type: any, base64Rest: any): string; +export function genUniqueKey(prefix: any): string; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/commonjs/utils.d.ts.map b/lib/typescript/commonjs/lib/commonjs/utils.d.ts.map new file mode 100644 index 0000000..cac0543 --- /dev/null +++ b/lib/typescript/commonjs/lib/commonjs/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../commonjs/utils.js"],"names":[],"mappings":";AAOA,8CAIC;AAOD,+DAGC;AAED,kDAKC"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/canvas-context.d.ts b/lib/typescript/commonjs/lib/module/canvas-context.d.ts new file mode 100644 index 0000000..3478321 --- /dev/null +++ b/lib/typescript/commonjs/lib/module/canvas-context.d.ts @@ -0,0 +1,3 @@ +export default CanvasContext; +declare const CanvasContext: import("react").Context; +//# sourceMappingURL=canvas-context.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/canvas-context.d.ts.map b/lib/typescript/commonjs/lib/module/canvas-context.d.ts.map new file mode 100644 index 0000000..00fbc1e --- /dev/null +++ b/lib/typescript/commonjs/lib/module/canvas-context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"canvas-context.d.ts","sourceRoot":"","sources":["../../../../module/canvas-context.js"],"names":[],"mappings":";AAGA,2DAAuD"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts b/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts new file mode 100644 index 0000000..3d2963c --- /dev/null +++ b/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts @@ -0,0 +1,4 @@ +declare const _default: React.NamedExoticComponent>; +export default _default; +import React from 'react'; +//# sourceMappingURL=drawing-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts.map b/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts.map new file mode 100644 index 0000000..18aec6a --- /dev/null +++ b/lib/typescript/commonjs/lib/module/drawing-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawing-canvas.d.ts","sourceRoot":"","sources":["../../../../module/drawing-canvas.js"],"names":[],"mappings":";;kBAK0E,OAAO"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts b/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts new file mode 100644 index 0000000..621f8ec --- /dev/null +++ b/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts @@ -0,0 +1,4 @@ +export default DrawnCanvas; +declare const DrawnCanvas: React.ForwardRefExoticComponent>; +import React from 'react'; +//# sourceMappingURL=drawn-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts.map b/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts.map new file mode 100644 index 0000000..e41fffd --- /dev/null +++ b/lib/typescript/commonjs/lib/module/drawn-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawn-canvas.d.ts","sourceRoot":"","sources":["../../../../module/drawn-canvas.js"],"names":[],"mappings":";AAQA,qFA2CG;kBA9CsD,OAAO"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/index.d.ts b/lib/typescript/commonjs/lib/module/index.d.ts new file mode 100644 index 0000000..f3c86e5 --- /dev/null +++ b/lib/typescript/commonjs/lib/module/index.d.ts @@ -0,0 +1,4 @@ +declare const _default: React.NamedExoticComponent>; +export default _default; +import React from 'react'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/index.d.ts.map b/lib/typescript/commonjs/lib/module/index.d.ts.map new file mode 100644 index 0000000..464d59e --- /dev/null +++ b/lib/typescript/commonjs/lib/module/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../module/index.js"],"names":[],"mappings":";;kBAEiI,OAAO"} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/styles.d.ts b/lib/typescript/commonjs/lib/module/styles.d.ts new file mode 100644 index 0000000..358a09d --- /dev/null +++ b/lib/typescript/commonjs/lib/module/styles.d.ts @@ -0,0 +1,19 @@ +declare namespace _default { + namespace flex1 { + let flex: number; + } + namespace container { + let flex_1: number; + export { flex_1 as flex }; + export let backgroundColor: string; + } + namespace canvas { + let position: "absolute"; + let top: number; + let left: number; + let right: number; + let bottom: number; + } +} +export default _default; +//# sourceMappingURL=styles.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/styles.d.ts.map b/lib/typescript/commonjs/lib/module/styles.d.ts.map new file mode 100644 index 0000000..909f296 --- /dev/null +++ b/lib/typescript/commonjs/lib/module/styles.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../module/styles.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/types.d.ts b/lib/typescript/commonjs/lib/module/types.d.ts new file mode 100644 index 0000000..78236dd --- /dev/null +++ b/lib/typescript/commonjs/lib/module/types.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/types.d.ts.map b/lib/typescript/commonjs/lib/module/types.d.ts.map new file mode 100644 index 0000000..47a156d --- /dev/null +++ b/lib/typescript/commonjs/lib/module/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../module/types.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/utils.d.ts b/lib/typescript/commonjs/lib/module/utils.d.ts new file mode 100644 index 0000000..605e67a --- /dev/null +++ b/lib/typescript/commonjs/lib/module/utils.d.ts @@ -0,0 +1,4 @@ +export function getSharedValue(val: any): any; +export function fillBase64(type: any, base64Rest: any): string; +export function genUniqueKey(prefix: any): string; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/commonjs/lib/module/utils.d.ts.map b/lib/typescript/commonjs/lib/module/utils.d.ts.map new file mode 100644 index 0000000..f7d7d6e --- /dev/null +++ b/lib/typescript/commonjs/lib/module/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../module/utils.js"],"names":[],"mappings":"AAGO,8CAIN;AAMM,+DAGN;AACM,kDAKN"} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/canvas-context.d.ts b/lib/typescript/module/lib/commonjs/canvas-context.d.ts new file mode 100644 index 0000000..ad8276c --- /dev/null +++ b/lib/typescript/module/lib/commonjs/canvas-context.d.ts @@ -0,0 +1,5 @@ +export const __esModule: boolean; +export default CanvasContext; +declare const CanvasContext: _react.Context; +import _react = require("react"); +//# sourceMappingURL=canvas-context.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/canvas-context.d.ts.map b/lib/typescript/module/lib/commonjs/canvas-context.d.ts.map new file mode 100644 index 0000000..30020f5 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/canvas-context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"canvas-context.d.ts","sourceRoot":"","sources":["../../../../commonjs/canvas-context.js"],"names":[],"mappings":";;AAOA,kDAAmE"} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts b/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts new file mode 100644 index 0000000..90ba43c --- /dev/null +++ b/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +declare const _default: any; +export default _default; +//# sourceMappingURL=drawing-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts.map b/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts.map new file mode 100644 index 0000000..bdcef6d --- /dev/null +++ b/lib/typescript/module/lib/commonjs/drawing-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawing-canvas.d.ts","sourceRoot":"","sources":["../../../../commonjs/drawing-canvas.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts b/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts new file mode 100644 index 0000000..7b8b4ff --- /dev/null +++ b/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +export default DrawnCanvas; +declare const DrawnCanvas: any; +//# sourceMappingURL=drawn-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts.map b/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts.map new file mode 100644 index 0000000..50733fe --- /dev/null +++ b/lib/typescript/module/lib/commonjs/drawn-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawn-canvas.d.ts","sourceRoot":"","sources":["../../../../commonjs/drawn-canvas.js"],"names":[],"mappings":";;AAeA,+BA2CG"} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/index.d.ts b/lib/typescript/module/lib/commonjs/index.d.ts new file mode 100644 index 0000000..012e0ad --- /dev/null +++ b/lib/typescript/module/lib/commonjs/index.d.ts @@ -0,0 +1,4 @@ +export const __esModule: boolean; +declare const _default: any; +export default _default; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/index.d.ts.map b/lib/typescript/module/lib/commonjs/index.d.ts.map new file mode 100644 index 0000000..841a279 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../commonjs/index.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/styles.d.ts b/lib/typescript/module/lib/commonjs/styles.d.ts new file mode 100644 index 0000000..def6295 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/styles.d.ts @@ -0,0 +1,20 @@ +export const __esModule: boolean; +declare namespace _default { + namespace flex1 { + let flex: number; + } + namespace container { + let flex_1: number; + export { flex_1 as flex }; + export let backgroundColor: string; + } + namespace canvas { + let position: "absolute"; + let top: number; + let left: number; + let right: number; + let bottom: number; + } +} +export default _default; +//# sourceMappingURL=styles.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/styles.d.ts.map b/lib/typescript/module/lib/commonjs/styles.d.ts.map new file mode 100644 index 0000000..e27c485 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/styles.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../commonjs/styles.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/types.d.ts b/lib/typescript/module/lib/commonjs/types.d.ts new file mode 100644 index 0000000..f89a43d --- /dev/null +++ b/lib/typescript/module/lib/commonjs/types.d.ts @@ -0,0 +1,2 @@ +export const __esModule: boolean; +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/types.d.ts.map b/lib/typescript/module/lib/commonjs/types.d.ts.map new file mode 100644 index 0000000..9ac3051 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../commonjs/types.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/utils.d.ts b/lib/typescript/module/lib/commonjs/utils.d.ts new file mode 100644 index 0000000..06dd39a --- /dev/null +++ b/lib/typescript/module/lib/commonjs/utils.d.ts @@ -0,0 +1,5 @@ +export const __esModule: boolean; +export function getSharedValue(val: any): any; +export function fillBase64(type: any, base64Rest: any): string; +export function genUniqueKey(prefix: any): string; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/commonjs/utils.d.ts.map b/lib/typescript/module/lib/commonjs/utils.d.ts.map new file mode 100644 index 0000000..cac0543 --- /dev/null +++ b/lib/typescript/module/lib/commonjs/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../commonjs/utils.js"],"names":[],"mappings":";AAOA,8CAIC;AAOD,+DAGC;AAED,kDAKC"} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/canvas-context.d.ts b/lib/typescript/module/lib/module/canvas-context.d.ts new file mode 100644 index 0000000..3478321 --- /dev/null +++ b/lib/typescript/module/lib/module/canvas-context.d.ts @@ -0,0 +1,3 @@ +export default CanvasContext; +declare const CanvasContext: import("react").Context; +//# sourceMappingURL=canvas-context.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/canvas-context.d.ts.map b/lib/typescript/module/lib/module/canvas-context.d.ts.map new file mode 100644 index 0000000..00fbc1e --- /dev/null +++ b/lib/typescript/module/lib/module/canvas-context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"canvas-context.d.ts","sourceRoot":"","sources":["../../../../module/canvas-context.js"],"names":[],"mappings":";AAGA,2DAAuD"} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/drawing-canvas.d.ts b/lib/typescript/module/lib/module/drawing-canvas.d.ts new file mode 100644 index 0000000..3d2963c --- /dev/null +++ b/lib/typescript/module/lib/module/drawing-canvas.d.ts @@ -0,0 +1,4 @@ +declare const _default: React.NamedExoticComponent>; +export default _default; +import React from 'react'; +//# sourceMappingURL=drawing-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/drawing-canvas.d.ts.map b/lib/typescript/module/lib/module/drawing-canvas.d.ts.map new file mode 100644 index 0000000..18aec6a --- /dev/null +++ b/lib/typescript/module/lib/module/drawing-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawing-canvas.d.ts","sourceRoot":"","sources":["../../../../module/drawing-canvas.js"],"names":[],"mappings":";;kBAK0E,OAAO"} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/drawn-canvas.d.ts b/lib/typescript/module/lib/module/drawn-canvas.d.ts new file mode 100644 index 0000000..621f8ec --- /dev/null +++ b/lib/typescript/module/lib/module/drawn-canvas.d.ts @@ -0,0 +1,4 @@ +export default DrawnCanvas; +declare const DrawnCanvas: React.ForwardRefExoticComponent>; +import React from 'react'; +//# sourceMappingURL=drawn-canvas.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/drawn-canvas.d.ts.map b/lib/typescript/module/lib/module/drawn-canvas.d.ts.map new file mode 100644 index 0000000..e41fffd --- /dev/null +++ b/lib/typescript/module/lib/module/drawn-canvas.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drawn-canvas.d.ts","sourceRoot":"","sources":["../../../../module/drawn-canvas.js"],"names":[],"mappings":";AAQA,qFA2CG;kBA9CsD,OAAO"} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/index.d.ts b/lib/typescript/module/lib/module/index.d.ts new file mode 100644 index 0000000..f3c86e5 --- /dev/null +++ b/lib/typescript/module/lib/module/index.d.ts @@ -0,0 +1,4 @@ +declare const _default: React.NamedExoticComponent>; +export default _default; +import React from 'react'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/index.d.ts.map b/lib/typescript/module/lib/module/index.d.ts.map new file mode 100644 index 0000000..464d59e --- /dev/null +++ b/lib/typescript/module/lib/module/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../module/index.js"],"names":[],"mappings":";;kBAEiI,OAAO"} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/styles.d.ts b/lib/typescript/module/lib/module/styles.d.ts new file mode 100644 index 0000000..358a09d --- /dev/null +++ b/lib/typescript/module/lib/module/styles.d.ts @@ -0,0 +1,19 @@ +declare namespace _default { + namespace flex1 { + let flex: number; + } + namespace container { + let flex_1: number; + export { flex_1 as flex }; + export let backgroundColor: string; + } + namespace canvas { + let position: "absolute"; + let top: number; + let left: number; + let right: number; + let bottom: number; + } +} +export default _default; +//# sourceMappingURL=styles.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/styles.d.ts.map b/lib/typescript/module/lib/module/styles.d.ts.map new file mode 100644 index 0000000..909f296 --- /dev/null +++ b/lib/typescript/module/lib/module/styles.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../module/styles.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/types.d.ts b/lib/typescript/module/lib/module/types.d.ts new file mode 100644 index 0000000..78236dd --- /dev/null +++ b/lib/typescript/module/lib/module/types.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/types.d.ts.map b/lib/typescript/module/lib/module/types.d.ts.map new file mode 100644 index 0000000..47a156d --- /dev/null +++ b/lib/typescript/module/lib/module/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../module/types.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/module/lib/module/utils.d.ts b/lib/typescript/module/lib/module/utils.d.ts new file mode 100644 index 0000000..605e67a --- /dev/null +++ b/lib/typescript/module/lib/module/utils.d.ts @@ -0,0 +1,4 @@ +export function getSharedValue(val: any): any; +export function fillBase64(type: any, base64Rest: any): string; +export function genUniqueKey(prefix: any): string; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/lib/typescript/module/lib/module/utils.d.ts.map b/lib/typescript/module/lib/module/utils.d.ts.map new file mode 100644 index 0000000..f7d7d6e --- /dev/null +++ b/lib/typescript/module/lib/module/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../module/utils.js"],"names":[],"mappings":"AAGO,8CAIN;AAMM,+DAGN;AACM,kDAKN"} \ No newline at end of file diff --git a/scripts/sync-example-pack.cjs b/scripts/sync-example-pack.cjs new file mode 100644 index 0000000..ff45519 --- /dev/null +++ b/scripts/sync-example-pack.cjs @@ -0,0 +1,40 @@ +'use strict'; + +/** + * Build the library, npm pack into `.pack/`, copy to a stable filename, and + * reinstall expo-example so it consumes the tarball (same layout as npm users). + * + * Skip the build step with: SKIP_LIB_BUILD=1 node scripts/sync-example-pack.cjs + */ + +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +const root = path.resolve(__dirname, '..'); +const packDir = path.join(root, '.pack'); +const exampleDir = path.join(root, 'expo-example'); +const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')); +const { version } = pkg; + +fs.mkdirSync(packDir, { recursive: true }); + +if (process.env.SKIP_LIB_BUILD !== '1') { + execSync('yarn build', { cwd: root, stdio: 'inherit' }); +} + +execSync('npm pack --pack-destination .pack', { cwd: root, stdio: 'inherit' }); + +const named = path.join(packDir, `react-native-free-canvas-${version}.tgz`); +const stable = path.join(packDir, 'react-native-free-canvas.tgz'); +if (!fs.existsSync(named)) { + throw new Error(`Expected pack at ${named}`); +} +fs.copyFileSync(named, stable); + +execSync( + `tar -tzf "${stable}" | grep -q 'package/lib/module/index.js' && tar -tzf "${stable}" | grep -q 'package/package.json'`, + { stdio: 'inherit', shell: '/bin/bash' }, +); + +execSync('yarn install --non-interactive', { cwd: exampleDir, stdio: 'inherit' }); From 57994c41ffdfdaf749b3c0171486d9f0c0ac3ace Mon Sep 17 00:00:00 2001 From: Lam Date: Mon, 27 Apr 2026 16:02:38 +0800 Subject: [PATCH 2/7] improve Demo UI --- expo-example/app/index.tsx | 672 +++++++++++++++++++++++++++++++++---- 1 file changed, 611 insertions(+), 61 deletions(-) diff --git a/expo-example/app/index.tsx b/expo-example/app/index.tsx index 44eb1fa..5e8018d 100644 --- a/expo-example/app/index.tsx +++ b/expo-example/app/index.tsx @@ -1,84 +1,634 @@ -import { StyleSheet, View, Button } from 'react-native'; -import React, { useRef, useState } from 'react'; -import FreeCanvas, { FreeCanvasRef } from 'react-native-free-canvas'; -import { Canvas, Image, Skia } from '@shopify/react-native-skia'; +import { + CornerPathEffect, + ImageFormat, + Path as SkiaPath, + Rect, + Canvas, + Image, + Skia, +} from '@shopify/react-native-skia'; +import React, { useCallback, useMemo, useRef, useState } from 'react'; +import { + Alert, + LayoutChangeEvent, + Pressable, + ScrollView, + Share, + StatusBar, + StyleSheet, + Switch, + Text, + View, +} from 'react-native'; +import { runOnJS } from 'react-native-reanimated'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +import FreeCanvas, { type FreeCanvasRef } from 'react-native-free-canvas'; + +const STROKE_PRESETS = [ + { color: '#38bdf8', label: 'Sky' }, + { color: '#f472b6', label: 'Pink' }, + { color: '#fbbf24', label: 'Amber' }, + { color: '#34d399', label: 'Mint' }, + { color: '#a78bfa', label: 'Violet' }, + { color: '#f8fafc', label: 'Snow' }, +] as const; + +const WIDTH_PRESETS = [4, 8, 14, 22] as const; + +const BG_PRESETS = ['#f1f5f9', '#ecfdf5', '#fff7ed', '#1e293b'] as const; + +const ZOOM_PRESETS: [number, number][] = [ + [0.35, 5], + [0.5, 2], + [0.8, 1.8], +]; + +function buildDotGridPath(width: number, height: number) { + const p = Skia.Path.Make(); + const step = 26; + for (let x = step; x < width; x += step) { + for (let y = step; y < height; y += step) { + p.addCircle(x, y, 1.25); + } + } + return p; +} + export default function HomeScreen() { const ref = useRef(null); - const [img, setImg] = useState(''); - const data = Skia.Data.fromBase64(img); - const image = Skia.Image.MakeImageFromEncoded(data); + const [canvasSize, setCanvasSize] = useState({ w: 0, h: 0 }); + const [strokeColor, setStrokeColor] = useState( + STROKE_PRESETS[0].color, + ); + const [strokeWidth, setStrokeWidth] = useState(8); + const [backgroundColor, setBackgroundColor] = useState(BG_PRESETS[0]); + const [smoothCorners, setSmoothCorners] = useState(true); + const [zoomable, setZoomable] = useState(true); + const [zoomRange, setZoomRange] = useState<[number, number]>(ZOOM_PRESETS[0]); + const [strokeCount, setStrokeCount] = useState(0); + const [snapshotB64, setSnapshotB64] = useState(null); + const [metrics, setMetrics] = useState({ + tx: 0, + ty: 0, + scale: 1, + ox: 0, + oy: 0, + }); + + const mergeMetrics = useCallback((patch: Partial) => { + setMetrics(m => ({ ...m, ...patch })); + }, []); + + const onTranslate = useCallback( + (x: number, y: number) => { + 'worklet'; + runOnJS(mergeMetrics)({ tx: x, ty: y }); + }, + [mergeMetrics], + ); + + const onScale = useCallback( + (scale: number) => { + 'worklet'; + runOnJS(mergeMetrics)({ scale }); + }, + [mergeMetrics], + ); + + const onTransformOriginChange = useCallback( + (x: number, y: number) => { + 'worklet'; + runOnJS(mergeMetrics)({ ox: x, oy: y }); + }, + [mergeMetrics], + ); + + const pathEffect = useMemo( + () => + smoothCorners ? ( + + ) : undefined, + [smoothCorners, strokeWidth], + ); + + const gridPath = useMemo(() => { + if (canvasSize.w < 8 || canvasSize.h < 8) { + return null; + } + return buildDotGridPath(canvasSize.w, canvasSize.h); + }, [canvasSize.w, canvasSize.h]); + + const foreground = useMemo(() => { + const w = Math.max(canvasSize.w, 1); + const h = Math.max(canvasSize.h, 1); + const t = 3; + const c = 'rgba(56, 189, 248, 0.45)'; + return ( + <> + + + + + + ); + }, [canvasSize.w, canvasSize.h]); + + const onCanvasLayout = useCallback((e: LayoutChangeEvent) => { + const { width, height } = e.nativeEvent.layout; + setCanvasSize({ w: width, h: height }); + }, []); + + const snapshotImage = useMemo(() => { + if (!snapshotB64) { + return null; + } + const data = Skia.Data.fromBase64(snapshotB64); + return Skia.Image.MakeImageFromEncoded(data); + }, [snapshotB64]); + + const capturePng = useCallback(async () => { + const b64 = await ref.current?.toBase64(ImageFormat.PNG, 92); + if (b64) { + setSnapshotB64(b64); + } else { + Alert.alert('Snapshot', 'Nothing to export yet — draw a stroke first.'); + } + }, []); + + const captureJpeg = useCallback(async () => { + const b64 = await ref.current?.toBase64(ImageFormat.JPEG, 88); + if (b64) { + setSnapshotB64(b64); + } else { + Alert.alert('Snapshot', 'Nothing to export yet — draw a stroke first.'); + } + }, []); + + const captureViaGetSnapshot = useCallback(async () => { + const img = await ref.current?.getSnapshot(); + if (!img) { + Alert.alert('getSnapshot', 'No image returned.'); + return; + } + const b64 = img.encodeToBase64(ImageFormat.PNG, 90); + setSnapshotB64(b64); + }, []); + + const sharePaths = useCallback(() => { + const paths = ref.current?.toPaths() ?? []; + const json = JSON.stringify(paths, null, 2); + Share.share({ message: json, title: 'Drawn paths' }).catch(() => {}); + }, []); + + const restoreDemo = useCallback(() => { + const paths = ref.current?.toPaths() ?? []; + if (paths.length === 0) { + Alert.alert('Paths', 'Draw something first, then use Restore demo.'); + return; + } + ref.current?.reset(); + requestAnimationFrame(() => { + ref.current?.drawPaths(paths); + }); + }, []); + + const handleUndo = useCallback(() => { + const steps = ref.current?.undo() as number | false | undefined; + if (typeof steps === 'number' && steps > 0) { + setStrokeCount(c => Math.max(0, c - steps)); + } + }, []); + return ( - - - - -