unframer 2.6.6 → 2.7.1
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 +9 -46
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +49 -44
- package/dist/cli.js.map +1 -1
- package/dist/css.js +1 -1
- package/dist/css.js.map +1 -1
- package/dist/esbuild.d.ts.map +1 -1
- package/dist/esbuild.js +7 -0
- package/dist/esbuild.js.map +1 -1
- package/dist/exporter.d.ts +16 -4
- package/dist/exporter.d.ts.map +1 -1
- package/dist/exporter.js +209 -49
- package/dist/exporter.js.map +1 -1
- package/dist/framer.d.ts.map +1 -1
- package/dist/framer.js +55 -19
- package/dist/framer.js.map +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +14 -1
- package/dist/utils.js.map +1 -1
- package/esm/cli.d.ts.map +1 -1
- package/esm/cli.js +49 -44
- package/esm/cli.js.map +1 -1
- package/esm/css.js +1 -1
- package/esm/css.js.map +1 -1
- package/esm/esbuild.d.ts.map +1 -1
- package/esm/esbuild.js +7 -0
- package/esm/esbuild.js.map +1 -1
- package/esm/exporter.d.ts +16 -4
- package/esm/exporter.d.ts.map +1 -1
- package/esm/exporter.js +208 -50
- package/esm/exporter.js.map +1 -1
- package/esm/framer.d.ts.map +1 -1
- package/esm/framer.js +55 -19
- package/esm/framer.js.map +1 -1
- package/esm/utils.d.ts +2 -0
- package/esm/utils.d.ts.map +1 -1
- package/esm/utils.js +12 -0
- package/esm/utils.js.map +1 -1
- package/package.json +8 -5
- package/src/cli.tsx +63 -57
- package/src/css.ts +1 -1
- package/src/esbuild.ts +10 -1
- package/src/exporter.ts +266 -57
- package/src/framer.js +72 -19
- package/src/utils.ts +17 -0
package/src/exporter.ts
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
logFontsUsage,
|
|
28
28
|
} from './css.js'
|
|
29
29
|
import dedent from 'dedent'
|
|
30
|
-
import { logger } from './utils.js'
|
|
30
|
+
import { logger, spinner, terminalMarkdown } from './utils.js'
|
|
31
31
|
import {
|
|
32
32
|
esbuildPluginBundleDependencies,
|
|
33
33
|
resolveRedirect,
|
|
@@ -42,10 +42,18 @@ function validateUrl(url: string) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
export type StyleToken = {
|
|
46
|
+
id: string
|
|
47
|
+
name?: string
|
|
48
|
+
lightColor: string
|
|
49
|
+
darkColor: string
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
export async function bundle({
|
|
46
53
|
cwd: out = '',
|
|
47
54
|
watch = false,
|
|
48
55
|
components = {} as Record<string, string>,
|
|
56
|
+
tokens = [] as StyleToken[],
|
|
49
57
|
breakpoints = {} as BreakpointSizes,
|
|
50
58
|
signal = undefined as AbortSignal | undefined,
|
|
51
59
|
}) {
|
|
@@ -55,6 +63,7 @@ export async function bundle({
|
|
|
55
63
|
fs.mkdirSync(out, { recursive: true })
|
|
56
64
|
} catch (e) {}
|
|
57
65
|
|
|
66
|
+
spinner.start()
|
|
58
67
|
const buildContext = await context({
|
|
59
68
|
// entryPoints: {
|
|
60
69
|
// index: url,
|
|
@@ -88,7 +97,7 @@ export async function bundle({
|
|
|
88
97
|
esbuildPluginBundleDependencies({
|
|
89
98
|
signal,
|
|
90
99
|
}),
|
|
91
|
-
polyfillNode({}),
|
|
100
|
+
polyfillNode({}) as any,
|
|
92
101
|
{
|
|
93
102
|
name: 'virtual loader',
|
|
94
103
|
setup(build) {
|
|
@@ -143,6 +152,7 @@ export async function bundle({
|
|
|
143
152
|
let codeNew =
|
|
144
153
|
`// @ts-nocheck\n` +
|
|
145
154
|
`/* eslint-disable */\n` +
|
|
155
|
+
'/* This file was generated by Unframer, do not edit manually */\n' +
|
|
146
156
|
dprint.format(resultPathAbs, file.text, {
|
|
147
157
|
lineWidth: 140,
|
|
148
158
|
quoteStyle: 'alwaysSingle',
|
|
@@ -151,14 +161,14 @@ export async function bundle({
|
|
|
151
161
|
})
|
|
152
162
|
const lines = findRelativeLinks(codeNew)
|
|
153
163
|
if (lines.length) {
|
|
154
|
-
|
|
164
|
+
spinner.error(
|
|
155
165
|
`found broken links for ${path.relative(
|
|
156
166
|
out,
|
|
157
167
|
file.path,
|
|
158
168
|
)}, don't use relative links in Framer components`,
|
|
159
169
|
)
|
|
160
170
|
lines.forEach((line) => {
|
|
161
|
-
logger.
|
|
171
|
+
logger.log(`${path.resolve(out, file.path)}:${line + 1}`)
|
|
162
172
|
})
|
|
163
173
|
}
|
|
164
174
|
|
|
@@ -168,6 +178,8 @@ export async function bundle({
|
|
|
168
178
|
logger.log(`writing`, path.relative(out, file.path))
|
|
169
179
|
fs.writeFileSync(resultPathAbs, codeNew, 'utf-8')
|
|
170
180
|
}
|
|
181
|
+
spinner.stop()
|
|
182
|
+
|
|
171
183
|
let allFonts = [] as ComponentFontBundle[]
|
|
172
184
|
const sema = new Sema(10)
|
|
173
185
|
const packageJson = path.resolve(out, 'package.json')
|
|
@@ -176,9 +188,13 @@ export async function bundle({
|
|
|
176
188
|
JSON.stringify({ type: 'module' }),
|
|
177
189
|
'utf-8',
|
|
178
190
|
)
|
|
191
|
+
if (!result?.outputFiles) {
|
|
192
|
+
throw new Error('Failed to generate result')
|
|
193
|
+
}
|
|
179
194
|
|
|
195
|
+
spinner.start('Extracting types')
|
|
180
196
|
const propControlsData = await Promise.all(
|
|
181
|
-
result
|
|
197
|
+
result?.outputFiles.map(async (file) => {
|
|
182
198
|
try {
|
|
183
199
|
await sema.acquire()
|
|
184
200
|
const name = path.basename(file.path).replace(/\.js$/, '')
|
|
@@ -187,6 +203,7 @@ export async function bundle({
|
|
|
187
203
|
return
|
|
188
204
|
}
|
|
189
205
|
logger.log(`extracting types for ${name}`)
|
|
206
|
+
spinner.update(`Extracting types for ${name}`)
|
|
190
207
|
const { propertyControls, fonts } =
|
|
191
208
|
await extractPropControlsUnsafe(resultPathAbs, name)
|
|
192
209
|
if (!propertyControls) {
|
|
@@ -215,16 +232,19 @@ export async function bundle({
|
|
|
215
232
|
}
|
|
216
233
|
}),
|
|
217
234
|
).finally(() => fs.rmSync(packageJson))
|
|
235
|
+
spinner.stop()
|
|
218
236
|
|
|
219
237
|
const cssString =
|
|
238
|
+
'/* This file was generated by Unframer, do not edit manually */\n' +
|
|
220
239
|
'/* This css file has all the necessary styles to run all your components */\n' +
|
|
240
|
+
'\n' +
|
|
241
|
+
getStyleTokensCss(tokens) +
|
|
221
242
|
breakpointsStyles(breakpoints) +
|
|
222
243
|
'\n\n' +
|
|
223
244
|
combinedCSSRules
|
|
224
245
|
.map((x) => (x?.startsWith(' ') ? dedent(x) : x))
|
|
225
246
|
.join('\n') +
|
|
226
247
|
getFontsStyles(allFonts)
|
|
227
|
-
|
|
228
248
|
fs.writeFileSync(path.resolve(out, 'styles.css'), cssString, 'utf-8')
|
|
229
249
|
|
|
230
250
|
logFontsUsage(allFonts)
|
|
@@ -263,12 +283,17 @@ export async function bundle({
|
|
|
263
283
|
if (watch) {
|
|
264
284
|
logger.log('waiting for components or config changes')
|
|
265
285
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
286
|
+
if (!tokens?.length) {
|
|
287
|
+
const tokensCss =
|
|
288
|
+
"/* This css file contains your color variables, sometimes these get desynced when updated in Framer so it's good that you copy and paste this snippet into your app css */\n" +
|
|
289
|
+
'/* Bug: https://www.framer.community/c/bugs/color-style-unlinks-when-copying-component-between-projects-resulting-in-potential-value-discrepancy */\n' +
|
|
290
|
+
getTokensCss({ out, result })
|
|
291
|
+
fs.writeFileSync(
|
|
292
|
+
path.resolve(out, 'tokens.css'),
|
|
293
|
+
tokensCss,
|
|
294
|
+
'utf-8',
|
|
295
|
+
)
|
|
296
|
+
}
|
|
272
297
|
const res = {
|
|
273
298
|
components: Object.entries(components).map(([name, v]) => {
|
|
274
299
|
const propControls = propControlsData.find(
|
|
@@ -284,60 +309,204 @@ export async function bundle({
|
|
|
284
309
|
}
|
|
285
310
|
}),
|
|
286
311
|
}
|
|
312
|
+
|
|
287
313
|
return res
|
|
288
314
|
}
|
|
289
315
|
|
|
290
316
|
if (!watch) {
|
|
291
317
|
const result = await rebuild()
|
|
292
318
|
await buildContext.dispose()
|
|
319
|
+
console.log()
|
|
320
|
+
console.log()
|
|
321
|
+
|
|
322
|
+
let exampleComponent = result?.components?.find((x) => {
|
|
323
|
+
if (!x.propertyControls) return false
|
|
324
|
+
const variants = getVariantsFromPropControls(x.propertyControls)
|
|
325
|
+
return variants?.breakpoints.length >= 2
|
|
326
|
+
})
|
|
327
|
+
if (!exampleComponent) {
|
|
328
|
+
logger.log(
|
|
329
|
+
`No example component found with breakpoints, using random example`,
|
|
330
|
+
)
|
|
331
|
+
// Create an example component if none found with breakpoints
|
|
332
|
+
exampleComponent = {
|
|
333
|
+
path: 'hero',
|
|
334
|
+
componentName: 'HeroFramerComponent',
|
|
335
|
+
propertyControls: {
|
|
336
|
+
variant: {
|
|
337
|
+
type: ControlType.Enum,
|
|
338
|
+
options: ['Desktop', 'Tablet', 'Mobile'],
|
|
339
|
+
optionTitles: ['Desktop', 'Tablet', 'Mobile'],
|
|
340
|
+
},
|
|
341
|
+
} as any,
|
|
342
|
+
name: 'Hero',
|
|
343
|
+
url: '',
|
|
344
|
+
}
|
|
345
|
+
if (!exampleComponent) {
|
|
346
|
+
return
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const variants = getVariantsFromPropControls(
|
|
350
|
+
exampleComponent?.propertyControls,
|
|
351
|
+
)
|
|
352
|
+
const breakpoints = variants?.breakpoints
|
|
353
|
+
if (!breakpoints) {
|
|
354
|
+
return
|
|
355
|
+
}
|
|
356
|
+
logger.log(
|
|
357
|
+
'exampleComponent?.propertyControls',
|
|
358
|
+
exampleComponent?.propertyControls,
|
|
359
|
+
)
|
|
360
|
+
const variantsExample = {
|
|
361
|
+
lg: breakpoints[1],
|
|
362
|
+
base: breakpoints[0],
|
|
363
|
+
}
|
|
364
|
+
let prop =
|
|
365
|
+
findExampleProperty(exampleComponent?.propertyControls) ||
|
|
366
|
+
'exampleFramerVariable'
|
|
367
|
+
const outDir = path.posix.relative(process.cwd(), out)
|
|
368
|
+
console.log(
|
|
369
|
+
terminalMarkdown(dedent`
|
|
370
|
+
# How to use the Framer components
|
|
371
|
+
|
|
372
|
+
Your components are exported to \`${outDir}\` folder. Now please install the \`unframer\` runtime dependency:
|
|
373
|
+
|
|
374
|
+
\`\`\`sh
|
|
375
|
+
npm install unframer
|
|
376
|
+
\`\`\`
|
|
377
|
+
|
|
378
|
+
Each component has a \`.Responsive\` variant that allows you to specify different variants for different breakpoints.
|
|
379
|
+
|
|
380
|
+
You can use the components like this (try copy pasting the code below into your React app):
|
|
381
|
+
|
|
382
|
+
\`\`\`jsx
|
|
383
|
+
import './${outDir}/styles.css'
|
|
384
|
+
import ${exampleComponent?.componentName} from './${outDir}/${
|
|
385
|
+
exampleComponent?.path
|
|
386
|
+
}'
|
|
387
|
+
|
|
388
|
+
export default function App() {
|
|
389
|
+
return (
|
|
390
|
+
<div>
|
|
391
|
+
<${exampleComponent?.componentName}
|
|
392
|
+
${prop}='example'
|
|
393
|
+
style={{ width: '100%' }}
|
|
394
|
+
/>
|
|
395
|
+
<${exampleComponent?.componentName}.Responsive
|
|
396
|
+
${prop}='example'
|
|
397
|
+
variants={${JSON.stringify(variantsExample || {})}}
|
|
398
|
+
/>
|
|
399
|
+
</div>
|
|
400
|
+
);
|
|
401
|
+
};
|
|
402
|
+
\`\`\`
|
|
403
|
+
|
|
404
|
+
It's very important to import the \`styles.css\` file to include the necessary styles for the components.
|
|
405
|
+
|
|
406
|
+
To style components you can pass a \`style\` or \`className\` prop (but remember to use !important to increase the specificity).
|
|
407
|
+
|
|
408
|
+
Read more on GitHub: https://github.com/remorses/unframer
|
|
409
|
+
`),
|
|
410
|
+
)
|
|
293
411
|
return result
|
|
294
412
|
}
|
|
295
413
|
|
|
296
|
-
// when user press ctrl+c dispose
|
|
297
|
-
process.on('SIGINT', async () => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
})
|
|
301
|
-
process.on('SIGABRT', async () => {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
})
|
|
305
|
-
signal?.addEventListener('abort', async () => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
})
|
|
414
|
+
// // when user press ctrl+c dispose
|
|
415
|
+
// process.on('SIGINT', async () => {
|
|
416
|
+
// await buildContext.cancel()
|
|
417
|
+
// buildContext.dispose()
|
|
418
|
+
// })
|
|
419
|
+
// process.on('SIGABRT', async () => {
|
|
420
|
+
// await buildContext.cancel()
|
|
421
|
+
// buildContext.dispose()
|
|
422
|
+
// })
|
|
423
|
+
// signal?.addEventListener('abort', async () => {
|
|
424
|
+
// await buildContext.cancel()
|
|
425
|
+
// buildContext.dispose()
|
|
426
|
+
// })
|
|
427
|
+
|
|
428
|
+
// const res = await rebuild()
|
|
429
|
+
|
|
430
|
+
// /**
|
|
431
|
+
// * Get resolved URLs for all components and also wait for 1 second if it took less time than that
|
|
432
|
+
// */
|
|
433
|
+
// const getResolvedUrls = () =>
|
|
434
|
+
// Promise.all([
|
|
435
|
+
// ...Object.values(components).map((u) => {
|
|
436
|
+
// const url = new URL(u)
|
|
437
|
+
// url.searchParams.set('ts', Date.now().toString())
|
|
438
|
+
// return resolveRedirect({ url: url.toString(), signal })
|
|
439
|
+
// }),
|
|
440
|
+
// new Promise((res) => setTimeout(res, 5000)),
|
|
441
|
+
// ])
|
|
442
|
+
// let prevUrls = await getResolvedUrls()
|
|
443
|
+
// while (!signal?.aborted) {
|
|
444
|
+
// const urls = await getResolvedUrls()
|
|
445
|
+
// const changed = urls
|
|
446
|
+
// .map((x, i) => (x !== prevUrls[i] ? i : null))
|
|
447
|
+
// .filter(Boolean)
|
|
448
|
+
// if (!changed?.length) {
|
|
449
|
+
// continue
|
|
450
|
+
// }
|
|
451
|
+
// const changedNames = Object.keys(components).filter((_, i) =>
|
|
452
|
+
// changed.includes(i),
|
|
453
|
+
// )
|
|
454
|
+
// logger.log(`found new component URLs for ${changedNames.join(', ')}`)
|
|
455
|
+
// prevUrls = urls
|
|
456
|
+
// await rebuild()
|
|
457
|
+
// }
|
|
458
|
+
// return res
|
|
459
|
+
}
|
|
309
460
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
])
|
|
324
|
-
let prevUrls = await getResolvedUrls()
|
|
325
|
-
while (!signal?.aborted) {
|
|
326
|
-
const urls = await getResolvedUrls()
|
|
327
|
-
const changed = urls
|
|
328
|
-
.map((x, i) => (x !== prevUrls[i] ? i : null))
|
|
329
|
-
.filter(Boolean)
|
|
330
|
-
if (!changed?.length) {
|
|
331
|
-
continue
|
|
332
|
-
}
|
|
333
|
-
const changedNames = Object.keys(components).filter((_, i) =>
|
|
334
|
-
changed.includes(i),
|
|
461
|
+
export function getDarkModeSelector(opts: {
|
|
462
|
+
darkModeType?: 'class' | 'media'
|
|
463
|
+
content: string
|
|
464
|
+
}) {
|
|
465
|
+
const { darkModeType = 'class', content } = opts
|
|
466
|
+
if (darkModeType === 'media') {
|
|
467
|
+
return (
|
|
468
|
+
'@media (prefers-color-scheme: dark) {\n' +
|
|
469
|
+
' :root {\n' +
|
|
470
|
+
content +
|
|
471
|
+
'\n' +
|
|
472
|
+
' }\n' +
|
|
473
|
+
'}'
|
|
335
474
|
)
|
|
336
|
-
logger.log(`found new component URLs for ${changedNames.join(', ')}`)
|
|
337
|
-
prevUrls = urls
|
|
338
|
-
await rebuild()
|
|
339
475
|
}
|
|
340
|
-
return
|
|
476
|
+
return '.dark:root {\n' + content + '\n' + '}'
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export function getStyleTokensCss(
|
|
480
|
+
tokens: StyleToken[],
|
|
481
|
+
darkModeType: 'class' | 'media' = 'class',
|
|
482
|
+
) {
|
|
483
|
+
if (!tokens?.length) {
|
|
484
|
+
return ''
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const lightTokens = tokens
|
|
488
|
+
.map(
|
|
489
|
+
(token) =>
|
|
490
|
+
' --token-' + token.id + ': ' + token.lightColor + ';',
|
|
491
|
+
)
|
|
492
|
+
.join('\n')
|
|
493
|
+
|
|
494
|
+
const darkTokens = tokens
|
|
495
|
+
.map(
|
|
496
|
+
(token) => ' --token-' + token.id + ': ' + token.darkColor + ';',
|
|
497
|
+
)
|
|
498
|
+
.join('\n')
|
|
499
|
+
|
|
500
|
+
return (
|
|
501
|
+
':root {\n' +
|
|
502
|
+
lightTokens +
|
|
503
|
+
'\n' +
|
|
504
|
+
'}\n\n' +
|
|
505
|
+
getDarkModeSelector({
|
|
506
|
+
darkModeType,
|
|
507
|
+
content: darkTokens,
|
|
508
|
+
})
|
|
509
|
+
)
|
|
341
510
|
}
|
|
342
511
|
|
|
343
512
|
function decapitalize(str: string) {
|
|
@@ -615,6 +784,7 @@ export function propControlsToType(controls: PropertyControls, fileName) {
|
|
|
615
784
|
.map((line) => ` ${line}`)
|
|
616
785
|
.join('\n') + '\n'
|
|
617
786
|
let t = ''
|
|
787
|
+
t += '/* This file was generated by Unframer, do not edit manually */\n'
|
|
618
788
|
t += 'import * as React from "react"\n\n'
|
|
619
789
|
t += 'import { UnframerBreakpoint } from "unframer"\n\n'
|
|
620
790
|
t += `export interface Props {\n${defaultPropsTypes}${types}\n}\n\n`
|
|
@@ -669,17 +839,17 @@ export function parsePropertyControls(code: string) {
|
|
|
669
839
|
return propControls.slice(realStart + 1, -1)
|
|
670
840
|
}
|
|
671
841
|
|
|
672
|
-
type
|
|
842
|
+
type ExtractedTokenInfo = {
|
|
673
843
|
tokenName: string
|
|
674
844
|
metadata?: Record<string, any>
|
|
675
845
|
|
|
676
846
|
defaultValue: string
|
|
677
847
|
}
|
|
678
848
|
|
|
679
|
-
export function extractTokenInfo(code: string):
|
|
849
|
+
export function extractTokenInfo(code: string): ExtractedTokenInfo[] {
|
|
680
850
|
const lines = code.split('\n')
|
|
681
851
|
const tokenLines = lines.filter((line) => line.includes('var(--token'))
|
|
682
|
-
const tokens:
|
|
852
|
+
const tokens: ExtractedTokenInfo[] = []
|
|
683
853
|
|
|
684
854
|
for (const line of tokenLines) {
|
|
685
855
|
let startIndex = 0
|
|
@@ -755,3 +925,42 @@ export function componentCamelCase(str: string) {
|
|
|
755
925
|
str = str + 'FramerComponent'
|
|
756
926
|
return str
|
|
757
927
|
}
|
|
928
|
+
|
|
929
|
+
const breakpointVariants = ['mobile', 'tablet', 'desktop']
|
|
930
|
+
|
|
931
|
+
function getVariantsFromPropControls(propControls?: PropertyControls) {
|
|
932
|
+
if (!propControls?.variant) {
|
|
933
|
+
return null
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
let variants =
|
|
937
|
+
propControls.variant?.['optionTitles'] ||
|
|
938
|
+
propControls.variant?.['options'] ||
|
|
939
|
+
[]
|
|
940
|
+
// Sort breakpoint-related variants first
|
|
941
|
+
return {
|
|
942
|
+
variants: variants,
|
|
943
|
+
breakpoints: variants.filter((v) =>
|
|
944
|
+
breakpointVariants.some((device) =>
|
|
945
|
+
v.toLowerCase().includes(device),
|
|
946
|
+
),
|
|
947
|
+
),
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
function findExampleProperty(propertyControls?: PropertyControls) {
|
|
952
|
+
if (!propertyControls) {
|
|
953
|
+
return null
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
const stringProp = Object.entries(propertyControls).find(([_, control]) => {
|
|
957
|
+
// console.log('control', _, control)
|
|
958
|
+
return control?.type === ControlType.String
|
|
959
|
+
})
|
|
960
|
+
|
|
961
|
+
if (!stringProp) {
|
|
962
|
+
return null
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
return stringProp[0]
|
|
966
|
+
}
|
package/src/framer.js
CHANGED
|
@@ -15349,7 +15349,7 @@ function steps(numSteps, direction = 'end',) {
|
|
|
15349
15349
|
};
|
|
15350
15350
|
}
|
|
15351
15351
|
|
|
15352
|
-
// https :https://app.framerstatic.com/framer.
|
|
15352
|
+
// https :https://app.framerstatic.com/framer.7SGKTLCE.mjs
|
|
15353
15353
|
init_chunk_QLPHEVXG();
|
|
15354
15354
|
import React4 from 'react';
|
|
15355
15355
|
import { startTransition as startTransition2, } from 'react';
|
|
@@ -18651,6 +18651,7 @@ function Router({
|
|
|
18651
18651
|
locales = EMPTY_ARRAY,
|
|
18652
18652
|
preserveQueryParams = false,
|
|
18653
18653
|
enableAsyncURLUpdates = false,
|
|
18654
|
+
LayoutTemplate,
|
|
18654
18655
|
},) {
|
|
18655
18656
|
useMarkRouterEffects();
|
|
18656
18657
|
useReplaceInitialState({
|
|
@@ -18879,14 +18880,27 @@ function Router({
|
|
|
18879
18880
|
notFoundPage,
|
|
18880
18881
|
defaultPageStyle,
|
|
18881
18882
|
forceUpdateKey: dep,
|
|
18882
|
-
children:
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18883
|
+
children: jsx(WithLayoutTemplate, {
|
|
18884
|
+
LayoutTemplate,
|
|
18885
|
+
routeId: currentRouteId,
|
|
18886
|
+
children: jsxs(Fragment, {
|
|
18887
|
+
children: [
|
|
18888
|
+
jsx(MarkSuspenseEffects.Start, {},),
|
|
18889
|
+
pageExistsInCurrentLocale
|
|
18890
|
+
? renderPage(
|
|
18891
|
+
current.page,
|
|
18892
|
+
LayoutTemplate
|
|
18893
|
+
? {
|
|
18894
|
+
...defaultPageStyle,
|
|
18895
|
+
display: 'content',
|
|
18896
|
+
}
|
|
18897
|
+
: defaultPageStyle,
|
|
18898
|
+
)
|
|
18899
|
+
: // LAYOUT_TEMPLATE @TODO: display: content for not found page?
|
|
18900
|
+
notFoundPage && renderPage(notFoundPage, defaultPageStyle,),
|
|
18901
|
+
],
|
|
18902
|
+
}, remountKey,),
|
|
18903
|
+
},),
|
|
18890
18904
|
},),
|
|
18891
18905
|
jsx(TurnOnReactEventHandling, {},),
|
|
18892
18906
|
jsx(MarkSuspenseEffects.End, {},),
|
|
@@ -18895,6 +18909,17 @@ function Router({
|
|
|
18895
18909
|
},),
|
|
18896
18910
|
},);
|
|
18897
18911
|
}
|
|
18912
|
+
function WithLayoutTemplate({
|
|
18913
|
+
LayoutTemplate,
|
|
18914
|
+
routeId,
|
|
18915
|
+
children,
|
|
18916
|
+
},) {
|
|
18917
|
+
if (!LayoutTemplate) return children;
|
|
18918
|
+
return jsx(LayoutTemplate, {
|
|
18919
|
+
routeId,
|
|
18920
|
+
children,
|
|
18921
|
+
},);
|
|
18922
|
+
}
|
|
18898
18923
|
function scrollElementIntoView(element, smoothScroll,) {
|
|
18899
18924
|
const scrollIntoViewOptions = smoothScroll
|
|
18900
18925
|
? {
|
|
@@ -36218,9 +36243,7 @@ function createHook(forwardedRef,) {
|
|
|
36218
36243
|
let preventNextCall = false;
|
|
36219
36244
|
function cloneChildrenWithPropsAndRef(children, props,) {
|
|
36220
36245
|
if (preventNextCall) {
|
|
36221
|
-
|
|
36222
|
-
'useCloneChildrenWithPropsAndRef: You should not call cloneChildrenWithPropsAndRef more than once during the render cycle.',
|
|
36223
|
-
);
|
|
36246
|
+
;
|
|
36224
36247
|
}
|
|
36225
36248
|
preventNextCall = true;
|
|
36226
36249
|
if (React2.Children.count(children,) > 1 && forwardedRef) {
|
|
@@ -42137,6 +42160,18 @@ var Ordering = class {
|
|
|
42137
42160
|
if (this.length !== other.length) return false;
|
|
42138
42161
|
return this.getHash() === other.getHash();
|
|
42139
42162
|
}
|
|
42163
|
+
providedByFields(fields,) {
|
|
42164
|
+
for (
|
|
42165
|
+
const {
|
|
42166
|
+
field,
|
|
42167
|
+
} of this.fields
|
|
42168
|
+
) {
|
|
42169
|
+
if (fields.has(field,)) continue;
|
|
42170
|
+
if (field.name === VIRTUAL_INDEX_FIELD) continue;
|
|
42171
|
+
return false;
|
|
42172
|
+
}
|
|
42173
|
+
return true;
|
|
42174
|
+
}
|
|
42140
42175
|
};
|
|
42141
42176
|
var Scope = class {
|
|
42142
42177
|
constructor(parent,) {
|
|
@@ -44740,13 +44775,21 @@ var Normalizer = class {
|
|
|
44740
44775
|
return this.newRelationalLeftJoin(right, left, constraint,);
|
|
44741
44776
|
}
|
|
44742
44777
|
newRelationalFilter(input, predicate,) {
|
|
44743
|
-
if (
|
|
44744
|
-
|
|
44745
|
-
|
|
44778
|
+
if (
|
|
44779
|
+
input instanceof RelationalLeftJoin &&
|
|
44780
|
+
// Check that the predicate doesn't depend on any joined field.
|
|
44781
|
+
predicate.referencedFields.subsetOf(input.leftGroup.relational.outputFields,)
|
|
44782
|
+
) {
|
|
44783
|
+
const pushedFilter = this.newRelationalFilter(input.left, predicate,);
|
|
44784
|
+
return this.newRelationalLeftJoin(pushedFilter, input.right, input.constraint,);
|
|
44746
44785
|
}
|
|
44747
|
-
if (
|
|
44748
|
-
|
|
44749
|
-
|
|
44786
|
+
if (
|
|
44787
|
+
input instanceof RelationalRightJoin &&
|
|
44788
|
+
// Check that the predicate doesn't depend on any joined field.
|
|
44789
|
+
predicate.referencedFields.subsetOf(input.rightGroup.relational.outputFields,)
|
|
44790
|
+
) {
|
|
44791
|
+
const pushedFilter = this.newRelationalFilter(input.right, predicate,);
|
|
44792
|
+
return this.newRelationalLeftJoin(input.left, pushedFilter, input.constraint,);
|
|
44750
44793
|
}
|
|
44751
44794
|
const node = new RelationalFilter(input, predicate,);
|
|
44752
44795
|
return this.finishRelational(node,);
|
|
@@ -44756,6 +44799,16 @@ var Normalizer = class {
|
|
|
44756
44799
|
return this.finishRelational(node,);
|
|
44757
44800
|
}
|
|
44758
44801
|
newRelationalLimit(input, limit, ordering,) {
|
|
44802
|
+
if (
|
|
44803
|
+
input instanceof RelationalProject &&
|
|
44804
|
+
// Check that the limit doesn't depend on any projected field.
|
|
44805
|
+
limit.referencedFields.subsetOf(input.inputGroup.relational.outputFields,) &&
|
|
44806
|
+
// Check that the ordering doesn't depend on any projected field.
|
|
44807
|
+
ordering.providedByFields(input.inputGroup.relational.outputFields,)
|
|
44808
|
+
) {
|
|
44809
|
+
const pushedLimit = this.newRelationalLimit(input.input, limit, ordering,);
|
|
44810
|
+
return this.newRelationalProject(pushedLimit, input.projections, input.passthrough,);
|
|
44811
|
+
}
|
|
44759
44812
|
const node = new RelationalLimit(input, limit, ordering,);
|
|
44760
44813
|
return this.finishRelational(node,);
|
|
44761
44814
|
}
|
|
@@ -53073,7 +53126,7 @@ var package_default = {
|
|
|
53073
53126
|
react: '^18.2.0',
|
|
53074
53127
|
'react-dom': '^18.2.0',
|
|
53075
53128
|
semver: '^7.5.2',
|
|
53076
|
-
typescript: '^5.
|
|
53129
|
+
typescript: '^5.7.2',
|
|
53077
53130
|
yargs: '^17.6.2',
|
|
53078
53131
|
},
|
|
53079
53132
|
peerDependencies: {
|
package/src/utils.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import pico from 'picocolors'
|
|
2
2
|
|
|
3
|
+
import { marked } from 'marked'
|
|
4
|
+
import { markedTerminal } from 'marked-terminal'
|
|
5
|
+
import { createSpinner } from 'nanospinner'
|
|
6
|
+
|
|
7
|
+
export const spinner = createSpinner('Downloading Framer Components') as any
|
|
8
|
+
|
|
9
|
+
marked.use(markedTerminal())
|
|
10
|
+
|
|
11
|
+
export function terminalMarkdown(markdown: string) {
|
|
12
|
+
return marked(markdown)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const shouldDebugUnframer = !!process.env.DEBUG_UNFRAMER
|
|
16
|
+
|
|
3
17
|
const prefix = '[unframer]'
|
|
4
18
|
export const logger = {
|
|
5
19
|
log(...args) {
|
|
20
|
+
if (!shouldDebugUnframer) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
6
23
|
console.log(prefix, ...args)
|
|
7
24
|
},
|
|
8
25
|
green(...args) {
|