diff --git a/examples/README.mdx b/examples/README.mdx new file mode 100644 index 0000000..8436362 --- /dev/null +++ b/examples/README.mdx @@ -0,0 +1,20 @@ +# Examples + +👨‍💼 These examples are here to help you *practice* what you have already learned +in the workshop. They are small, practical projects that keep the focus on the +foundational skills: values, variables, functions, control flow, loops, and +basic types. + +📜 There are **no solutions** and **no tests** in this section. That is +intentional. This is about exploring, practicing, and building confidence by +applying workshop concepts to something that feels real. + +🤔 You may see code that looks unfamiliar (React, Vite, styling, etc.). Feel +free to explore it, but you do not need to master it right now. Focus on the +areas with 🐨 instructions. Those are the parts that line up with what you've +learned so far. + +🧠 **Spaced repetition** helps you remember what you learn by revisiting it over +time. Practical examples like these give you lots of reps and quick wins, which +makes the concepts stick and builds momentum. + diff --git a/examples/muffin-shop-checkout/index.ts b/examples/muffin-shop-checkout/index.ts new file mode 100644 index 0000000..0be3304 --- /dev/null +++ b/examples/muffin-shop-checkout/index.ts @@ -0,0 +1,95 @@ +// Muffin Shop Checkout +// Build a simple receipt for a muffin shop order. + +const shopName = 'Morning Muffins' +const customerName = 'Avery' +const isMember = true +const muffinCount = 3 +const coffeeCount = 2 +const muffinPrice = 3.25 +const coffeePrice = 4 +const tipPercent = 0.15 +const taxRate = 0.0825 +const pickupMethod = 'counter' + +function buildDivider(char: string, length: number) { + // 🐨 Build and return a divider string by repeating char + // 💰 Start with let line = '' and add char in a for loop + let line = '' + return line +} + +function formatMoney(amount: number) { + // 🐨 Return a string like `$4.5` using a template literal + return `$${amount}` +} + +function calculateDiscount(subtotal: number, member: boolean) { + // 🐨 If the customer is a member and subtotal is at least 15, + // return 10% of subtotal. Otherwise return 0. + return 0 +} + +function calculateTax(subtotal: number, rate: number) { + // 🐨 Return subtotal multiplied by rate + return 0 +} + +function calculateTip(totalBeforeTip: number, percent: number) { + // 🐨 Return totalBeforeTip multiplied by percent + return 0 +} + +function calculatePickupFee(method: string) { + // 🐨 Use a switch statement to return: + // 'counter' -> 0 + // 'curbside' -> 3 + // 'delivery' -> 7 + return 0 +} + +let subtotal = 0 +// 🐨 Set subtotal using item counts and prices +// 💰 (muffinCount * muffinPrice) + (coffeeCount * coffeePrice) + +const discount = calculateDiscount(subtotal, isMember) +const taxableAmount = subtotal - discount +const tax = calculateTax(taxableAmount, taxRate) +const tip = calculateTip(taxableAmount + tax, tipPercent) +const pickupFee = calculatePickupFee(pickupMethod) + +let pickupLabel = '' +// 🐨 If pickupFee is 0, set pickupLabel to 'FREE' +// otherwise set it to formatMoney(pickupFee) + +let memberMessage = '' +// 🐨 If isMember is true, set memberMessage to 'Member discount applied' +// otherwise set it to 'Join the club for 10% off' + +let total = 0 +// 🐨 Set total using subtotal, discount, tax, tip, and pickupFee + +const header = buildDivider('=', 32) +const divider = buildDivider('-', 32) + +const receipt = + `${header}\n` + + `${shopName}\n` + + `Order for ${customerName}\n` + + `${divider}\n` + + `Muffins: ${muffinCount} x ${formatMoney(muffinPrice)}\n` + + `Coffee: ${coffeeCount} x ${formatMoney(coffeePrice)}\n` + + `${divider}\n` + + `Subtotal: ${formatMoney(subtotal)}\n` + + `Discount: -${formatMoney(discount)}\n` + + `Tax: ${formatMoney(tax)}\n` + + `Tip: ${formatMoney(tip)}\n` + + `Pickup fee: ${pickupLabel}\n` + + `${divider}\n` + + `Total: ${formatMoney(total)}\n` + + `${memberMessage}\n` + + `${header}` + +console.log(receipt) + +export { receipt } diff --git a/examples/muffin-shop-checkout/package.json b/examples/muffin-shop-checkout/package.json new file mode 100644 index 0000000..758896c --- /dev/null +++ b/examples/muffin-shop-checkout/package.json @@ -0,0 +1,7 @@ +{ + "name": "examples_muffin-shop-checkout", + "type": "module", + "scripts": { + "start": "npx @kentcdodds/log-module ./index.ts" + } +} diff --git a/examples/muffin-shop-checkout/readme.mdx b/examples/muffin-shop-checkout/readme.mdx new file mode 100644 index 0000000..1d1ad2d --- /dev/null +++ b/examples/muffin-shop-checkout/readme.mdx @@ -0,0 +1,61 @@ +# Muffin Shop Checkout + +👨‍💼 The muffin shop needs a simple receipt that totals an order and prints a +clean summary for customers. + +📜 This example sticks to the skills from the workshop: numbers, strings, +booleans, variables, functions, if/else, switch statements, and loops. + +🐨 Open and complete the following tasks: + +1. Build the divider string with a loop. +2. Calculate `subtotal`. +3. Implement `calculateDiscount`. +4. Implement `calculateTax`. +5. Implement `calculateTip`. +6. Implement `calculatePickupFee` with a switch statement. +7. Set `pickupLabel` with an if/else. +8. Set `memberMessage` with an if/else. +9. Calculate `total`. +10. Make sure the receipt prints with `console.log`. + +💰 Flip `isMember` to see the discount and message change. +💰 Try `pickupMethod` as `curbside` or `delivery` to test the switch logic. + +## Run the example + +```sh nonumber +npm run start --workspace examples/muffin-shop-checkout +``` + +## What the output can look like + +Here is a sample console receipt output: + +```text +================================ +Morning Muffins +Order for Avery +-------------------------------- +Muffins: 3 x $3.25 +Coffee: 2 x $4 +-------------------------------- +Subtotal: $17.75 +Discount: -$1.78 +Tax: $1.31 +Tip: $2.86 +Pickup fee: FREE +-------------------------------- +Total: $20.14 +Member discount applied +================================ +``` + +## Try next + +- 🐨 Add a `dailySpecialCount` and `dailySpecialPrice`, then include them in the + `subtotal`. +- 🐨 Create a `hasCoupon` boolean and apply an extra discount with an `if` check. +- 🐨 Use a loop to build a `summaryLine` like `Items: 5 total`. +- 🐨 Add a `rushOrder` flag that increases the `tipPercent` when true. +- 💰 Try a new `pickupMethod` value and update the switch to handle it. diff --git a/examples/muffin-shop-dashboard/index.html b/examples/muffin-shop-dashboard/index.html new file mode 100644 index 0000000..cf05f09 --- /dev/null +++ b/examples/muffin-shop-dashboard/index.html @@ -0,0 +1,12 @@ + + + + + + Muffin Shop Dashboard + + +
+ + + diff --git a/examples/muffin-shop-dashboard/package.json b/examples/muffin-shop-dashboard/package.json new file mode 100644 index 0000000..f345f18 --- /dev/null +++ b/examples/muffin-shop-dashboard/package.json @@ -0,0 +1,21 @@ +{ + "name": "examples_muffin-shop-dashboard", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.3", + "react-dom": "^19.2.3" + }, + "devDependencies": { + "@types/react": "^19.2.8", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.2", + "typescript": "^5.9.3", + "vite": "^7.3.1" + } +} diff --git a/examples/muffin-shop-dashboard/readme.mdx b/examples/muffin-shop-dashboard/readme.mdx new file mode 100644 index 0000000..c36a105 --- /dev/null +++ b/examples/muffin-shop-dashboard/readme.mdx @@ -0,0 +1,40 @@ +# Muffin Shop Dashboard + +👨‍💼 The muffin shop wants a simple dashboard for a single order so the team can +double-check totals before handing it off. + +📜 This example uses React + Vite, but everything React-related is already done +for you. You only need the workshop skills: numbers, strings, booleans, +variables, functions, if/else, switch statements, loops, and `never`. + +🐨 Open and complete the following tasks: + +1. Format money with a template literal. +2. Add the `(GF)` label for gluten-free items. +3. Sum the subtotal with a loop. +4. Apply the member discount. +5. Calculate tax and tip. +6. Calculate the final total. +7. Return the pickup fee with a switch statement. +8. Return the pickup label with a switch statement. +9. Format the special note when it's empty. +10. Log the ready message. +11. Implement `assertNever`. + +💰 Toggle `memberStatus` or `pickupMethod` in to +see different outputs. + +## Run the example + +```sh nonumber +npm run dev --workspace examples/muffin-shop-dashboard +``` + +## Try next + +- 🐨 Add another `OrderItem` and watch the totals change. +- 🐨 Add a `rushOrder` boolean and increase the tip when it is true. +- 🐨 Add a `itemCount` helper that uses a loop to count total quantity. +- 🐨 Add a `happyHour` boolean and reduce the muffin price when true. +- 🐨 Add a `memberMessage` string in `app.tsx` using an `if` check. +- 💰 Change `specialNote` to a real note and confirm the fallback logic. diff --git a/examples/muffin-shop-dashboard/src/app.css b/examples/muffin-shop-dashboard/src/app.css new file mode 100644 index 0000000..6f5ae29 --- /dev/null +++ b/examples/muffin-shop-dashboard/src/app.css @@ -0,0 +1,114 @@ +.app { + max-width: 960px; + margin: 0 auto; + padding: 32px 24px 48px; +} + +.app-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + margin-bottom: 24px; +} + +.app-header h1 { + margin: 4px 0 0; + font-size: 32px; +} + +.eyebrow { + margin: 0; + font-size: 12px; + letter-spacing: 0.2em; + text-transform: uppercase; + color: #8a6f5a; +} + +.badge { + background: #fff; + border-radius: 999px; + padding: 8px 16px; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.12em; + color: #5b4a3f; + box-shadow: 0 8px 24px rgba(59, 45, 34, 0.08); +} + +.layout { + display: grid; + gap: 24px; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); +} + +.card { + background: #fff; + border-radius: 16px; + padding: 24px; + box-shadow: 0 16px 40px rgba(59, 45, 34, 0.08); +} + +.card h2 { + margin-top: 0; + margin-bottom: 16px; +} + +.line-items { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 12px; +} + +.line-item { + display: flex; + justify-content: space-between; + gap: 16px; + font-weight: 600; +} + +.note { + margin-top: 16px; + padding-top: 12px; + border-top: 1px solid #efe5db; + display: flex; + justify-content: space-between; + gap: 12px; + font-size: 14px; + color: #6f655b; +} + +.summary-row { + display: flex; + justify-content: space-between; + gap: 16px; + margin-top: 8px; +} + +.summary-row.total { + margin-top: 16px; + padding-top: 12px; + border-top: 1px solid #efe5db; + font-size: 18px; + font-weight: 700; +} + +.pill { + margin-top: 16px; + display: inline-block; + padding: 6px 12px; + border-radius: 999px; + background: #f1e4d7; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: #6a4d3b; +} + +.helper { + margin-top: 12px; + font-size: 14px; + color: #6f655b; +} diff --git a/examples/muffin-shop-dashboard/src/app.tsx b/examples/muffin-shop-dashboard/src/app.tsx new file mode 100644 index 0000000..c05f81a --- /dev/null +++ b/examples/muffin-shop-dashboard/src/app.tsx @@ -0,0 +1,123 @@ +import './app.css' +import { + buildLineItemText, + calculateDiscount, + calculateSubtotal, + calculateTax, + calculateTip, + calculateTotal, + formatMoney, + formatNote, + getPickupFee, + getPickupLabel, + logOrderReady, + type MemberStatus, + type OrderItem, + type PickupMethod, +} from './muffin-utils' + +const shopName = 'Morning Muffins' +const customerName = 'Avery' +const memberStatus: MemberStatus = 'member' +const pickupMethod: PickupMethod = 'curbside' +const specialNote: string | null = null +const taxRate = 0.0825 +const tipPercent = 0.12 + +const orderItems: OrderItem[] = [ + { + name: 'Blueberry Muffin', + price: 3.25, + quantity: 2, + isGlutenFree: false, + }, + { + name: 'Oatberry Muffin', + price: 4.25, + quantity: 1, + isGlutenFree: true, + }, + { + name: 'Cold Brew', + price: 4.5, + quantity: 1, + isGlutenFree: true, + }, +] + +const subtotal = calculateSubtotal(orderItems) +const discount = calculateDiscount(subtotal, memberStatus) +const taxableAmount = subtotal - discount +const tax = calculateTax(taxableAmount, taxRate) +const tip = calculateTip(taxableAmount + tax, tipPercent) +const pickupFee = getPickupFee(pickupMethod) +const total = calculateTotal(subtotal, discount, tax, tip, pickupFee) + +const pickupLabel = getPickupLabel(pickupMethod) +const noteLabel = formatNote(specialNote) + +export function App() { + logOrderReady(customerName) + + return ( +
+
+
+

Order summary

+

{shopName}

+
+
+ {memberStatus === 'member' ? 'Member pricing' : 'Guest order'} +
+
+ +
+
+

Items

+
    + {orderItems.map((item) => ( +
  • + {buildLineItemText(item)} + {formatMoney(item.price * item.quantity)} +
  • + ))} +
+
+ Special notes + {noteLabel} +
+
+ +
+

Totals

+
+ Subtotal + {formatMoney(subtotal)} +
+
+ Discount + -{formatMoney(discount)} +
+
+ Tax + {formatMoney(tax)} +
+
+ Tip + {formatMoney(tip)} +
+
+ Pickup fee + {formatMoney(pickupFee)} +
+
+ Total + {formatMoney(total)} +
+
{pickupLabel}
+

Customer: {customerName}

+
+
+
+ ) +} diff --git a/examples/muffin-shop-dashboard/src/index.css b/examples/muffin-shop-dashboard/src/index.css new file mode 100644 index 0000000..727ba20 --- /dev/null +++ b/examples/muffin-shop-dashboard/src/index.css @@ -0,0 +1,19 @@ +:root { + font-family: 'Inter', 'Segoe UI', system-ui, sans-serif; + color: #2f2a25; + background-color: #f8f3ee; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-height: 100vh; + background-color: #f8f3ee; +} + +#root { + min-height: 100vh; +} diff --git a/examples/muffin-shop-dashboard/src/main.tsx b/examples/muffin-shop-dashboard/src/main.tsx new file mode 100644 index 0000000..39b371a --- /dev/null +++ b/examples/muffin-shop-dashboard/src/main.tsx @@ -0,0 +1,16 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import { App } from './app' + +const rootElement = document.getElementById('root') + +if (!rootElement) { + throw new Error('Root element not found') +} + +createRoot(rootElement).render( + + + , +) diff --git a/examples/muffin-shop-dashboard/src/muffin-utils.ts b/examples/muffin-shop-dashboard/src/muffin-utils.ts new file mode 100644 index 0000000..8f8fd82 --- /dev/null +++ b/examples/muffin-shop-dashboard/src/muffin-utils.ts @@ -0,0 +1,106 @@ +type OrderItem = { + name: string + price: number + quantity: number + isGlutenFree: boolean +} + +type MemberStatus = 'member' | 'guest' +type PickupMethod = 'counter' | 'curbside' | 'delivery' + +function formatMoney(amount: number) { + // 🐨 Return a string like `$4.5` using a template literal + // 💰 return `$${amount}` + return '$0' +} + +function buildLineItemText(item: OrderItem) { + // 🐨 Return a string like `2 x Blueberry Muffin (GF)` + // 💰 Use item.quantity, item.name, and item.isGlutenFree + let glutenFreeLabel = '' + // 🐨 If item.isGlutenFree is true, set glutenFreeLabel to ' (GF)' + return `${item.quantity} x ${item.name}${glutenFreeLabel}` +} + +function calculateSubtotal(items: OrderItem[]) { + // 🐨 Use a for loop to add each item total to subtotal + // 💰 Use item.price * item.quantity inside the loop + let subtotal = 0 + return subtotal +} + +function calculateDiscount(subtotal: number, status: MemberStatus) { + // 🐨 If status is 'member' and subtotal is at least 20, + // return 10% of subtotal. Otherwise return 0. + return 0 +} + +function calculateTax(taxableAmount: number, rate: number) { + // 🐨 Return taxableAmount multiplied by rate + return 0 +} + +function calculateTip(totalBeforeTip: number, percent: number) { + // 🐨 Return totalBeforeTip multiplied by percent + return 0 +} + +function calculateTotal( + subtotal: number, + discount: number, + tax: number, + tip: number, + pickupFee: number, +) { + // 🐨 Return the final total using subtotal, discount, tax, tip, and pickupFee + return 0 +} + +function getPickupFee(method: PickupMethod) { + // 🐨 Use a switch statement to return: + // 'counter' -> 0 + // 'curbside' -> 3 + // 'delivery' -> 7 + return 0 +} + +function getPickupLabel(method: PickupMethod) { + // 🐨 Return a label for the pickup method: + // 'counter' -> 'Counter pickup' + // 'curbside' -> 'Curbside pickup' + // 'delivery' -> 'Delivery dropoff' + // 💰 Use a switch statement with assertNever in the default case + return method +} + +function formatNote(note: string | null) { + // 🐨 If note is null or an empty string, return 'No special notes' + // otherwise return the note + return note ?? '' +} + +function logOrderReady(customer: string): void { + // 🐨 Use console.log to print `Order ready for ${customer}` +} + +function assertNever(value: never): never { + // 🐨 Throw an error so TypeScript knows this never happens + // 💰 throw new Error(`Unhandled case: ${value}`) + throw new Error('Unhandled case') +} + +export { + assertNever, + buildLineItemText, + calculateDiscount, + calculateSubtotal, + calculateTax, + calculateTip, + calculateTotal, + formatMoney, + formatNote, + getPickupFee, + getPickupLabel, + logOrderReady, +} +export type { MemberStatus, OrderItem, PickupMethod } diff --git a/examples/muffin-shop-dashboard/tsconfig.json b/examples/muffin-shop-dashboard/tsconfig.json new file mode 100644 index 0000000..d494c5f --- /dev/null +++ b/examples/muffin-shop-dashboard/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true + }, + "include": ["src"] +} diff --git a/examples/muffin-shop-dashboard/vite.config.ts b/examples/muffin-shop-dashboard/vite.config.ts new file mode 100644 index 0000000..9ffcc67 --- /dev/null +++ b/examples/muffin-shop-dashboard/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], +}) diff --git a/package-lock.json b/package-lock.json index c4fd6da..7b33868 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,23 @@ "npm": ">=8.16.0" } }, + "examples/muffin-shop-checkout": { + "name": "examples_muffin-shop-checkout" + }, + "examples/muffin-shop-dashboard": { + "name": "examples_muffin-shop-dashboard", + "dependencies": { + "react": "^19.2.3", + "react-dom": "^19.2.3" + }, + "devDependencies": { + "@types/react": "^19.2.8", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.2", + "typescript": "^5.9.3", + "vite": "^7.3.1" + } + }, "exercises/01.expressions-and-output/01.problem.hello-world": { "name": "exercises_01.expressions-and-output_01.problem.hello-world" }, @@ -341,6 +358,16 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -396,6 +423,38 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", @@ -2078,6 +2137,363 @@ } } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz", + "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", @@ -2718,6 +3134,51 @@ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "license": "MIT" }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -2851,6 +3312,26 @@ "@types/pg": "*" } }, + "node_modules/@types/react": { + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", + "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, "node_modules/@types/resolve": { "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", @@ -3393,6 +3874,27 @@ "win32" ] }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz", + "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.5", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.53", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, "node_modules/@vitest/eslint-plugin": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.6.tgz", @@ -4161,6 +4663,13 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "license": "MIT" }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -5263,6 +5772,14 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/examples_muffin-shop-checkout": { + "resolved": "examples/muffin-shop-checkout", + "link": true + }, + "node_modules/examples_muffin-shop-dashboard": { + "resolved": "examples/muffin-shop-dashboard", + "link": true + }, "node_modules/execa": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", @@ -8443,6 +8960,25 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/napi-postinstall": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", @@ -9014,6 +9550,35 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -9335,6 +9900,16 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "license": "MIT" }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-router": { "version": "7.12.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.12.0.tgz", @@ -9813,6 +10388,51 @@ "node": ">=0.10.0" } }, + "node_modules/rollup": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10144,6 +10764,16 @@ "node": ">= 12" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -11190,6 +11820,109 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",