unframer 2.11.2 → 2.13.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.
Files changed (49) hide show
  1. package/dist/exporter.d.ts +3 -0
  2. package/dist/exporter.d.ts.map +1 -1
  3. package/dist/exporter.js +70 -32
  4. package/dist/exporter.js.map +1 -1
  5. package/dist/exporter.test.js +3 -0
  6. package/dist/exporter.test.js.map +1 -1
  7. package/dist/framer.d.ts.map +1 -1
  8. package/dist/framer.js +876 -507
  9. package/dist/framer.js.map +1 -1
  10. package/dist/index.d.ts +3 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +9 -5
  13. package/dist/index.js.map +1 -1
  14. package/dist/react.d.ts +16 -6
  15. package/dist/react.d.ts.map +1 -1
  16. package/dist/react.js +70 -3
  17. package/dist/react.js.map +1 -1
  18. package/dist/utils.d.ts +3 -2
  19. package/dist/utils.d.ts.map +1 -1
  20. package/dist/utils.js +27 -2
  21. package/dist/utils.js.map +1 -1
  22. package/esm/exporter.d.ts +3 -0
  23. package/esm/exporter.d.ts.map +1 -1
  24. package/esm/exporter.js +72 -35
  25. package/esm/exporter.js.map +1 -1
  26. package/esm/exporter.test.js +4 -1
  27. package/esm/exporter.test.js.map +1 -1
  28. package/esm/framer.d.ts.map +1 -1
  29. package/esm/framer.js +873 -507
  30. package/esm/framer.js.map +1 -1
  31. package/esm/index.d.ts +3 -1
  32. package/esm/index.d.ts.map +1 -1
  33. package/esm/index.js +3 -1
  34. package/esm/index.js.map +1 -1
  35. package/esm/react.d.ts +16 -6
  36. package/esm/react.d.ts.map +1 -1
  37. package/esm/react.js +69 -5
  38. package/esm/react.js.map +1 -1
  39. package/esm/utils.d.ts +3 -2
  40. package/esm/utils.d.ts.map +1 -1
  41. package/esm/utils.js +26 -2
  42. package/esm/utils.js.map +1 -1
  43. package/package.json +3 -4
  44. package/src/exporter.test.ts +6 -1
  45. package/src/exporter.ts +85 -42
  46. package/src/framer.js +925 -513
  47. package/src/index.ts +7 -1
  48. package/src/react.tsx +104 -16
  49. package/src/utils.ts +30 -3
package/src/index.ts CHANGED
@@ -1,8 +1,14 @@
1
1
  export * from './framer.js'
2
-
2
+ import {
3
+ AdaptedLink as Link,
4
+ ResolveLinksAdapted as ResolveLinks,
5
+ } from './react.js'
3
6
  export {
4
7
  FramerStyles,
5
8
  UnframerBreakpoint,
6
9
  WithFramerBreakpoints,
7
10
  ContextProviders,
11
+ AdaptedLink,
8
12
  } from './react.js'
13
+
14
+ export { Link, ResolveLinks }
package/src/react.tsx CHANGED
@@ -229,36 +229,124 @@ import {
229
229
  FormContext,
230
230
  // @ts-ignore
231
231
  Router,
232
+ // @ts-ignore
233
+ LocaleInfoContext,
234
+ // @ts-ignore
235
+ FramerLink as Link,
232
236
  } from './framer.js'
237
+ import React from 'react'
238
+
239
+ type Routes = Record<string, { path: string }>
240
+
241
+ const routesContext = React.createContext<Routes>({})
242
+
243
+ function replacePathParams(path: string, params: Record<string, string>) {
244
+ const paramRegex = /:[a-zA-Z]+/g
245
+ const matches = path.match(paramRegex)
246
+
247
+ // If there is only one match
248
+ if (matches?.length === 1) {
249
+ const paramValue = Object.values(params)[0]
250
+
251
+ let res = path.replace(paramRegex, paramValue)
252
+ // console.log({ matches, params, paramValue, res })
253
+
254
+ return res
255
+ }
256
+
257
+ return path.replace(paramRegex, (match) => {
258
+ const param = match.slice(1) // Remove the : prefix
259
+ return params[param] || match // Replace with param value or keep original if not found
260
+ })
261
+ }
262
+
263
+ export function ResolveLinksAdapted({ links, children }) {
264
+ // TODO add ref
265
+ return children(links.map((x) => x.href))
266
+ }
267
+
268
+ export function AdaptedLink({
269
+ href,
270
+ nodeId,
271
+ openInNewTab,
272
+ smoothScroll,
273
+ children,
274
+ ...rest
275
+ }) {
276
+
277
+ const onlyForFramer = { children, nodeId, openInNewTab, smoothScroll }
278
+ const routes = React.useContext(routesContext)
279
+ const webPageId = href?.webPageId as string
280
+ const pathVariables = href?.pathVariables as Record<string, string>
281
+ const route = routes?.[webPageId]
282
+ const target = openInNewTab ? '_blank' : undefined
283
+ // console.log({ href, pathVariables, path: route?.path, ...rest })
284
+ if (href?.startsWith && href.startsWith('/')) {
285
+ return React.cloneElement(children, { ...rest, href, target })
286
+ }
287
+ if (!webPageId) {
288
+ return <Link href={href} {...rest} {...onlyForFramer} />
289
+ }
290
+
291
+ if (!route || !route.path) {
292
+ return <Link href={href} {...rest} {...onlyForFramer} />
293
+ }
294
+ let path = route.path
295
+ if (pathVariables) {
296
+ path = replacePathParams(path, pathVariables)
297
+ }
298
+ if (path?.startsWith?.('/')) {
299
+ return React.cloneElement(children, {
300
+ ...rest,
301
+ href: path,
302
+ target,
303
+ })
304
+ }
305
+
306
+ return <Link href={path} {...rest} {...onlyForFramer} />
307
+ }
233
308
 
234
309
  export function ContextProviders({
235
310
  locale,
236
311
  children,
237
312
  framerSiteId,
238
313
  routes,
239
- routeId,
240
- pathVariables,
241
- collectionUtils,
314
+ // collectionUtils,
242
315
  locales,
243
316
  }) {
244
- const localeId = locales?.find(
317
+ const activeLocale = locales?.find(
245
318
  (l) => l.slug === locale || l.code === locale || l.id === locale,
246
- )?.id
319
+ )
320
+
321
+ const localeInfo = useMemo(() => {
322
+ return {
323
+ activeLocale,
324
+ locales,
325
+ setLocale: async (localeOrLocaleId) => {
326
+ console.log('setLocale', localeOrLocaleId)
327
+ },
328
+ }
329
+ }, [activeLocale, locales])
247
330
  return (
248
331
  <FetchClientProvider>
249
332
  <CustomCursorHost>
250
333
  <FormContext.Provider value={framerSiteId}>
251
- <Router
252
- initialRoute={routeId}
253
- initialPathVariables={pathVariables}
254
- initialLocaleId={localeId}
255
- enableImproveInpDuringHydration={true}
256
- routes={routes}
257
- collectionUtils={collectionUtils}
258
- locales={locales}
259
- >
260
- {children}
261
- </Router>
334
+ <LocaleInfoContext value={localeInfo}>
335
+ <routesContext.Provider value={routes}>
336
+ {/* <Router
337
+ initialRoute='x'
338
+ routes={{
339
+ x: { page: children, path: '/' },
340
+ ...routes,
341
+ }}
342
+ locales={locales}
343
+ initialLocaleId={activeLocale?.id}
344
+ >
345
+ {children}
346
+ </Router> */}
347
+ {children}
348
+ </routesContext.Provider>
349
+ </LocaleInfoContext>
262
350
  </FormContext.Provider>
263
351
  </CustomCursorHost>
264
352
  </FetchClientProvider>
package/src/utils.ts CHANGED
@@ -4,7 +4,7 @@ import { marked } from 'marked'
4
4
  import { markedTerminal } from 'marked-terminal'
5
5
  import { createSpinner } from 'nanospinner'
6
6
 
7
- export const spinner = createSpinner('Downloading Framer Components') as any
7
+ export const spinner = createSpinner('Downloading Framer Components')
8
8
 
9
9
  marked.use(markedTerminal())
10
10
 
@@ -31,8 +31,7 @@ export const logger = {
31
31
  },
32
32
  }
33
33
 
34
- export async function componentNameToPath(name: string) {
35
- const { default: kebabCase } = await import('just-kebab-case')
34
+ export function componentNameToPath(name: string) {
36
35
  return name
37
36
  .split('/')
38
37
  .filter(Boolean)
@@ -43,3 +42,31 @@ export async function componentNameToPath(name: string) {
43
42
  export function sleep(ms: number) {
44
43
  return new Promise((resolve) => setTimeout(resolve, ms))
45
44
  }
45
+
46
+ // https://www.npmjs.com/package/just-kebab-case?activeTab=readme
47
+ // any combination of spaces and punctuation characters
48
+ // thanks to http://stackoverflow.com/a/25575009
49
+ var wordSeparators =
50
+ /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]+/
51
+ var capital_plus_lower = /[A-ZÀ-Ý\u00C0-\u00D6\u00D9-\u00DD][a-zà-ÿ]/g
52
+ var capitals = /[A-ZÀ-Ý\u00C0-\u00D6\u00D9-\u00DD]+/g
53
+
54
+ export function kebabCase(str: string) {
55
+ // replace word starts with space + lower case equivalent for later parsing
56
+ // 1) treat cap + lower as start of new word
57
+ str = str.replace(capital_plus_lower, function (match) {
58
+ // match is one caps followed by one non-cap
59
+ return ' ' + (match[0].toLowerCase() || match[0]) + match[1]
60
+ })
61
+ // 2) treat all remaining capitals as words
62
+ str = str.replace(capitals, function (match) {
63
+ // match is a series of caps
64
+ return ' ' + match.toLowerCase()
65
+ })
66
+ return str
67
+ .trim()
68
+ .split(wordSeparators)
69
+ .join('-')
70
+ .replace(/^-/, '')
71
+ .replace(/-\s*$/, '')
72
+ }