your-ai-workflow-firebase-os 1.11.1 β†’ 1.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 (38) hide show
  1. package/README.md +6 -5
  2. package/dist/assets/PhoneInputField-BV9b08_J.js +1 -0
  3. package/dist/assets/PhoneInputField-wv5RvJiD.css +1 -0
  4. package/dist/{aiRules-Rc2v45Ew.cjs β†’ assets/aiRules-CY6YKVrB.js} +70 -36
  5. package/dist/assets/index-B-YmRzN2.js +459 -0
  6. package/dist/assets/index-CvDlnie_.css +2 -0
  7. package/dist/assets/index.esm-IRo3eskp.js +1 -0
  8. package/dist/assets/jsx-runtime-DyTGnfRu.js +1 -0
  9. package/dist/index.html +16 -0
  10. package/package.json +1 -1
  11. package/dist/ContactPopup-Dl7zmx84.cjs +0 -1
  12. package/dist/ContactPopup-pbomk9Le.js +0 -1320
  13. package/dist/PhoneInputField-BdzUG4Wx.cjs +0 -1
  14. package/dist/PhoneInputField-DCaTvHA8.js +0 -2043
  15. package/dist/SetupPayments-87F-r6-p.js +0 -2251
  16. package/dist/SetupPayments-CqzaXhjP.cjs +0 -389
  17. package/dist/SetupPayments-DBDDg1By.cjs +0 -1
  18. package/dist/TimeZoneField-BM2gaSxF.js +0 -46216
  19. package/dist/TimeZoneField-DgZkxTbz.cjs +0 -10
  20. package/dist/aiRules-Cx71S6Lf.js +0 -3
  21. package/dist/chunk-DYteiM-1.cjs +0 -1
  22. package/dist/renderer.cjs.js +0 -1
  23. package/dist/renderer.es.js +0 -2
  24. package/dist/server.cjs.js +0 -11
  25. package/dist/server.es.js +0 -1106
  26. package/dist/src/FirebaseOS.d.ts +0 -44
  27. package/dist/src/index.d.ts +0 -30
  28. package/dist/src/lib/AuthContext.d.ts +0 -31
  29. package/dist/src/lib/ConfigContext.d.ts +0 -40
  30. package/dist/src/lib/ThemeContext.d.ts +0 -36
  31. package/dist/src/renderer.d.ts +0 -1
  32. package/dist/src/server/index.d.ts +0 -124
  33. package/dist/src/vite/index.d.ts +0 -9
  34. package/dist/vite.cjs.js +0 -176
  35. package/dist/vite.es.js +0 -584
  36. package/dist/your-ai-workflow-firebase-os.cjs.js +0 -23
  37. package/dist/your-ai-workflow-firebase-os.css +0 -2
  38. package/dist/your-ai-workflow-firebase-os.es.js +0 -18978
package/README.md CHANGED
@@ -27,15 +27,16 @@ That's it. **One component. Zero configuration files.**
27
27
  |:--------|:--------|
28
28
  | πŸ” **Authentication** | Email/password, email verification, password reset |
29
29
  | πŸ‘₯ **User Management** | Admin panel, three access levels (Free Β· Internal Β· Admin), inactive user blocking |
30
- | πŸ—‚οΈ **Pages** | Ask your AI assistant for a page β€” for anyone, signed-in users, your team or admins only β€” and it appears in `/pages`, where you rename it, reorder it, hide it or change its web address |
30
+ | πŸ—‚οΈ **Pages** | Add a page on `/pages` β€” for anyone, signed-in users, your team or admins only β€” in one box that shows what to say before you type: its name, address, heading, what it is for, its form, its pictures, its booking, a page it links to; upload the pictures under it. Copy the sentence and the assistant builds it, deciding whatever was skipped; the page then shows all its settings on `/pages`, where you rename it, reorder it, hide it or change its web address, and Edit with AI takes one box saying what should change |
31
31
  | πŸ“‹ **Templates** | Board (Kanban), Calendar, Table, Drive, Inline Form, Popup Form, Confirmation |
32
32
  | 🎨 **Theme Engine** | Full dark/light mode, custom accent colours, corner radii, logo |
33
33
  | πŸ“ **File Storage** | An admin-only Assets screen for public images, plus a drive preset any page can be built on |
34
- | πŸ“¬ **Forms** | Created with their pages on `/pages` β€” say what a form should ask and the AI builds it with the page; see and hand-edit every form afterwards on `/forms`. Questions can ask for a file β€” a CV, a photo, a receipt β€” and the upload works signed out |
34
+ | πŸ“¬ **Forms** | Created with their pages on `/pages` β€” say in one box what a form should ask and what happens after (or name one you already have) and the AI builds it with the page; see and hand-edit every form afterwards on `/forms`. Questions can ask for a file β€” a CV, a photo, a receipt β€” and the upload works signed out |
35
35
  | πŸ“₯ **Inbox** | Every form entry in one list at `/inbox`, filtered "From anyone" or "From signed-in users"; an attached file opens from the entry by its own name |
36
- | πŸ’³ **Payments** | Stripe checkout in one line β€” the owner configures what they sell under What you sell on `/payments` (a price and a name, or plans and their Stripe ids), then answers How your payments work: how the payment works, what a buyer says first, what happens after. Pages are wired on `/pages`: a page ticks the payment under Payments on this page and says what should happen there β€” public and signed-in pages sell with `<PayButton>`, internal and admin pages show the team the sales through `useSales()`, and a page linked to either asks the same question from its side. The page's own sentence builds it, asking any before-paying questions through the app's own forms. A Go live switch walks the testβ†’live change (live price ids collected, test ids kept, and the id-swap prompt for the assistant generated), buyers get a built-in `/billing` page that appears after their first purchase, and every cancel/switch/invoice screen is Stripe's own billing portal |
37
- | πŸ“… **Schedule** | Bookings in one form question β€” on `/schedule` each team member sets their bookable hours in their own time zone (days, from–to, how long a booking lasts, how far ahead, how much notice); the owner attaches it on `/pages` under Booking on this page or as a Pick-a-time question on `/forms`, and the page's own sentence asks the assistant for ONE `schedule` field in a `*Form.config.ts`. The built-in form draws the picker β€” a full calendar or a compact day-and-time list β€” in every visitor's own time zone, claims the time so two people can never take the same minute, saves the booking as a form entry in the Inbox (one readable line, with the time on the owner's own clock under it), and lists it on `/schedule` where it can be cancelled; a team page reads them with `useBookings()`. The assistant never builds a calendar, a time picker or a bookings collection |
38
- | βœ‰οΈ **Email** | Resend in one line β€” every page can send email once it is connected: `emailOwner()` tells the owner what happened, `emailPerson()` confirms to the person a record names, `emailAnyone()` lets a team page write to any address (a signed-in admin or team member only), receipts and sale alerts send themselves off a Pay button's settings, and `/email` says what the app can do with email and where owner mail goes |
36
+ | πŸ’³ **Payments** | Stripe checkout in one line β€” a Take payments switch at the top of `/payments` pauses every Pay button and checkout at once (read by the server, so a built page stops too), then the owner configures what they sell under What you sell on `/payments` (things paid for once β€” each a name and a price, grouped under one entry β€” or plans and their Stripe ids), answers How your payments work in one box per payment (start to finish; whatever is skipped, the AI decides), then under Wire it into your pages opens each payment a third time, ticks the pages THAT payment goes on and, optionally, says what should appear there or names a page to add β€” and copies ONE request that wires all of it: the exact `<PayButton>` tags, each page's content file, the owner's words, and the way this app makes a page, a form and a link β€” public and signed-in pages sell with `<PayButton>`, internal and admin pages show the team the sales through `useSales()`, and before-paying questions go through the app's own forms. A Go live switch, shown under Connection once the webhook is in, walks the testβ†’live change (live price ids collected, test ids kept, and the id-swap prompt for the assistant generated), buyers get a built-in `/billing` page that appears after their first purchase, and every cancel/switch/invoice screen is Stripe's own billing portal |
37
+ | πŸ“… **Schedule** | Calendly-style booking, built in β€” on `/schedule` the owner adds schedules, one per kind of meeting a team member offers (a 1-hour session, a 2-hour workshop): a name, a line about it, whose time it is, the hours in that person's own time zone, the length, how far ahead, how much notice, and a one-time payment taken first when they want one. A person's schedules share one availability, so a time booked under any of them is gone from all. Every schedule has a shipped booking page at `/book/{id}` to send as a link β€” the app's theme and name, a full calendar in the visitor's own time zone, name, email, a note, and Stripe checkout before the time is confirmed when a payment is attached. Every team member gets a My calendar tab at `/my-calendar` the moment a schedule exists for them: every booking made with them on a month grid, Paid beside the paid ones, Cancel to free the time. A schedule can also be picked on `/pages` under Booking on this page (one per person, from a select) or as a Pick-a-time question on `/forms`, and the page's sentence asks the assistant for ONE `schedule` field in a `*Form.config.ts`; the built-in form draws the picker, claims the time so two people can never take the same minute, and saves the booking as a form entry in the Inbox. The assistant never builds a calendar, a time picker or a bookings collection |
38
+ | πŸ”— **Payment links** | Every one-time payment has a shipped page at `/pay/{id}` in the app's theme and name β€” under Payment links on `/payments` the owner adds one from a name, a line about it and a price, copies the link and sends it to anyone; Customise this page makes a real page on `/pages` and hands over the sentence that builds it, and the link goes there once it is built |
39
+ | βœ‰οΈ **Email** | Resend in one line β€” a Send email switch at the top of `/email` stops every send at once (the server reads it before each one); while it is on, every page can send email once it is connected: `emailOwner()` tells the owner what happened, `emailPerson()` confirms to the person a record names, `emailAnyone()` lets a team page write to any address (a signed-in admin or team member only), receipts and sale alerts send themselves off a Pay button's settings, and `/email` says what the app can do with email and where owner mail goes |
39
40
  | πŸ“– **Guide** | A walkthrough at `/guide` with the sentences to paste into your assistant |
40
41
  | πŸ“Š **Dashboard** | Personalised user dashboard |
41
42
 
@@ -0,0 +1 @@
1
+ import{n as e,s as t,t as n}from"./jsx-runtime-DyTGnfRu.js";var r=t(e(),1),i=[[`Afghanistan`,`af`,`93`],[`Albania`,`al`,`355`],[`Algeria`,`dz`,`213`],[`Andorra`,`ad`,`376`],[`Angola`,`ao`,`244`],[`Antigua and Barbuda`,`ag`,`1268`],[`Argentina`,`ar`,`54`,{default:`(..) .... ....`,"/^11/":`(..) .... ....`,"/^15/":`(..) ... ....`,"/^(2|3|4|5)/":`(.) .... ....`,"/^9/":`(.) .... .....`},0],[`Armenia`,`am`,`374`,`.. ......`],[`Aruba`,`aw`,`297`],[`Australia`,`au`,`61`,{default:`. .... ....`,"/^4/":`... ... ...`,"/^5(?!50)/":`... ... ...`,"/^1(3|8)00/":`.... ... ...`,"/^13/":`.. .. ..`,"/^180/":`... ....`},0,[]],[`Austria`,`at`,`43`],[`Azerbaijan`,`az`,`994`,`(..) ... .. ..`],[`Bahamas`,`bs`,`1242`],[`Bahrain`,`bh`,`973`,`.... ....`],[`Bangladesh`,`bd`,`880`],[`Barbados`,`bb`,`1246`],[`Belarus`,`by`,`375`,`(..) ... .. ..`],[`Belgium`,`be`,`32`,`... .. .. ..`],[`Belize`,`bz`,`501`],[`Benin`,`bj`,`229`],[`Bhutan`,`bt`,`975`],[`Bolivia`,`bo`,`591`],[`Bosnia and Herzegovina`,`ba`,`387`],[`Botswana`,`bw`,`267`],[`Brazil`,`br`,`55`,`(..) .....-....`],[`British Indian Ocean Territory`,`io`,`246`],[`Brunei`,`bn`,`673`],[`Bulgaria`,`bg`,`359`],[`Burkina Faso`,`bf`,`226`],[`Burundi`,`bi`,`257`],[`Cambodia`,`kh`,`855`],[`Cameroon`,`cm`,`237`],[`Canada`,`ca`,`1`,`(...) ...-....`,1,`204.226.236.249.250.289.306.343.365.387.403.416.418.431.437.438.450.506.514.519.548.579.581.587.604.613.639.647.672.705.709.742.778.780.782.807.819.825.867.873.902.905`.split(`.`)],[`Cape Verde`,`cv`,`238`],[`Caribbean Netherlands`,`bq`,`599`,``,1],[`Cayman Islands`,`ky`,`1`,`... ... ....`,4,[`345`]],[`Central African Republic`,`cf`,`236`],[`Chad`,`td`,`235`],[`Chile`,`cl`,`56`],[`China`,`cn`,`86`,`... .... ....`],[`Colombia`,`co`,`57`,`... ... ....`],[`Comoros`,`km`,`269`],[`Congo`,`cd`,`243`],[`Congo`,`cg`,`242`],[`Costa Rica`,`cr`,`506`,`....-....`],[`CΓ΄te d'Ivoire`,`ci`,`225`,`.. .. .. .. ..`],[`Croatia`,`hr`,`385`],[`Cuba`,`cu`,`53`],[`CuraΓ§ao`,`cw`,`599`,``,0],[`Cyprus`,`cy`,`357`,`.. ......`],[`Czech Republic`,`cz`,`420`,`... ... ...`],[`Denmark`,`dk`,`45`,`.. .. .. ..`],[`Djibouti`,`dj`,`253`,`.. .. ....`],[`Dominica`,`dm`,`1767`],[`Dominican Republic`,`do`,`1`,`(...) ...-....`,2,[`809`,`829`,`849`]],[`Ecuador`,`ec`,`593`],[`Egypt`,`eg`,`20`],[`El Salvador`,`sv`,`503`,`....-....`],[`Equatorial Guinea`,`gq`,`240`],[`Eritrea`,`er`,`291`],[`Estonia`,`ee`,`372`,`.... ......`],[`Ethiopia`,`et`,`251`,`.. ... ....`],[`Faroe Islands`,`fo`,`298`,`.. .. ..`],[`Fiji`,`fj`,`679`],[`Finland`,`fi`,`358`,`.. ... .. ..`],[`France`,`fr`,`33`,`. .. .. .. ..`],[`French Guiana`,`gf`,`594`,`... .. .. ..`],[`French Polynesia`,`pf`,`689`,{"/^44/":`.. .. ..`,"/^80[0-5]/":`... .. .. ..`,default:`.. .. .. ..`}],[`Gabon`,`ga`,`241`],[`Gambia`,`gm`,`220`],[`Georgia`,`ge`,`995`],[`Germany`,`de`,`49`,`... .........`],[`Ghana`,`gh`,`233`],[`Gibraltar`,`gi`,`350`],[`Greece`,`gr`,`30`],[`Greenland`,`gl`,`299`,`.. .. ..`],[`Grenada`,`gd`,`1473`],[`Guadeloupe`,`gp`,`590`,`... .. .. ..`,0],[`Guam`,`gu`,`1671`],[`Guatemala`,`gt`,`502`,`....-....`],[`Guinea`,`gn`,`224`],[`Guinea-Bissau`,`gw`,`245`],[`Guyana`,`gy`,`592`],[`Haiti`,`ht`,`509`,`....-....`],[`Honduras`,`hn`,`504`],[`Hong Kong`,`hk`,`852`,`.... ....`],[`Hungary`,`hu`,`36`],[`Iceland`,`is`,`354`,`... ....`],[`India`,`in`,`91`,`.....-.....`],[`Indonesia`,`id`,`62`],[`Iran`,`ir`,`98`,`... ... ....`],[`Iraq`,`iq`,`964`],[`Ireland`,`ie`,`353`,`.. .......`],[`Israel`,`il`,`972`,`... ... ....`],[`Italy`,`it`,`39`,`... .......`,0],[`Jamaica`,`jm`,`1876`],[`Japan`,`jp`,`81`,`.. .... ....`],[`Jordan`,`jo`,`962`],[`Kazakhstan`,`kz`,`7`,`... ...-..-..`,0],[`Kenya`,`ke`,`254`],[`Kiribati`,`ki`,`686`],[`Kosovo`,`xk`,`383`],[`Kuwait`,`kw`,`965`,`.... ....`],[`Kyrgyzstan`,`kg`,`996`,`... ... ...`],[`Laos`,`la`,`856`],[`Latvia`,`lv`,`371`,`.. ... ...`],[`Lebanon`,`lb`,`961`],[`Lesotho`,`ls`,`266`],[`Liberia`,`lr`,`231`],[`Libya`,`ly`,`218`],[`Liechtenstein`,`li`,`423`],[`Lithuania`,`lt`,`370`],[`Luxembourg`,`lu`,`352`],[`Macau`,`mo`,`853`],[`Macedonia`,`mk`,`389`],[`Madagascar`,`mg`,`261`],[`Malawi`,`mw`,`265`],[`Malaysia`,`my`,`60`,`..-....-....`],[`Maldives`,`mv`,`960`],[`Mali`,`ml`,`223`],[`Malta`,`mt`,`356`],[`Marshall Islands`,`mh`,`692`],[`Martinique`,`mq`,`596`,`... .. .. ..`],[`Mauritania`,`mr`,`222`],[`Mauritius`,`mu`,`230`],[`Mayotte`,`yt`,`262`,`... .. .. ..`,1,[`269`,`639`]],[`Mexico`,`mx`,`52`,`... ... ....`,0],[`Micronesia`,`fm`,`691`],[`Moldova`,`md`,`373`,`(..) ..-..-..`],[`Monaco`,`mc`,`377`],[`Mongolia`,`mn`,`976`],[`Montenegro`,`me`,`382`],[`Morocco`,`ma`,`212`],[`Mozambique`,`mz`,`258`],[`Myanmar`,`mm`,`95`],[`Namibia`,`na`,`264`],[`Nauru`,`nr`,`674`],[`Nepal`,`np`,`977`],[`Netherlands`,`nl`,`31`,{"/^06/":`(.). .........`,"/^6/":`. .........`,"/^0(10|13|14|15|20|23|24|26|30|33|35|36|38|40|43|44|45|46|50|53|55|58|70|71|72|73|74|75|76|77|78|79|82|84|85|87|88|91)/":`(.).. ........`,"/^(10|13|14|15|20|23|24|26|30|33|35|36|38|40|43|44|45|46|50|53|55|58|70|71|72|73|74|75|76|77|78|79|82|84|85|87|88|91)/":`.. ........`,"/^0/":`(.)... .......`,default:`... .......`}],[`New Caledonia`,`nc`,`687`],[`New Zealand`,`nz`,`64`,`...-...-....`],[`Nicaragua`,`ni`,`505`],[`Niger`,`ne`,`227`],[`Nigeria`,`ng`,`234`],[`North Korea`,`kp`,`850`],[`Norway`,`no`,`47`,`... .. ...`],[`Oman`,`om`,`968`,`.... ....`],[`Pakistan`,`pk`,`92`,`...-.......`],[`Palau`,`pw`,`680`],[`Palestine`,`ps`,`970`],[`Panama`,`pa`,`507`],[`Papua New Guinea`,`pg`,`675`],[`Paraguay`,`py`,`595`],[`Peru`,`pe`,`51`],[`Philippines`,`ph`,`63`,`... ... ....`],[`Poland`,`pl`,`48`,`...-...-...`],[`Portugal`,`pt`,`351`],[`Puerto Rico`,`pr`,`1`,`(...) ...-....`,3,[`787`,`939`]],[`Qatar`,`qa`,`974`,`.... ....`],[`RΓ©union`,`re`,`262`,`... .. .. ..`,0],[`Romania`,`ro`,`40`],[`Russia`,`ru`,`7`,`(...) ...-..-..`,1],[`Rwanda`,`rw`,`250`],[`Saint Kitts and Nevis`,`kn`,`1869`],[`Saint Lucia`,`lc`,`1758`],[`Saint Pierre & Miquelon`,`pm`,`508`,{"/^708/":`... ... ...`,"/^8/":`... .. .. ..`,default:`.. .. ..`}],[`Saint Vincent and the Grenadines`,`vc`,`1784`],[`Samoa`,`ws`,`685`],[`San Marino`,`sm`,`378`],[`SΓ£o TomΓ© and PrΓ­ncipe`,`st`,`239`],[`Saudi Arabia`,`sa`,`966`,`.. ... ....`],[`Senegal`,`sn`,`221`],[`Serbia`,`rs`,`381`],[`Seychelles`,`sc`,`248`],[`Sierra Leone`,`sl`,`232`],[`Singapore`,`sg`,`65`,`....-....`],[`Slovakia`,`sk`,`421`],[`Slovenia`,`si`,`386`],[`Solomon Islands`,`sb`,`677`],[`Somalia`,`so`,`252`],[`South Africa`,`za`,`27`],[`South Korea`,`kr`,`82`,`... .... ....`],[`South Sudan`,`ss`,`211`],[`Spain`,`es`,`34`,`... ... ...`],[`Sri Lanka`,`lk`,`94`],[`Sudan`,`sd`,`249`],[`Suriname`,`sr`,`597`],[`Swaziland`,`sz`,`268`],[`Sweden`,`se`,`46`,`... ... ...`],[`Switzerland`,`ch`,`41`,`.. ... .. ..`],[`Syria`,`sy`,`963`],[`Taiwan`,`tw`,`886`],[`Tajikistan`,`tj`,`992`],[`Tanzania`,`tz`,`255`],[`Thailand`,`th`,`66`],[`Timor-Leste`,`tl`,`670`],[`Togo`,`tg`,`228`],[`Tonga`,`to`,`676`],[`Trinidad and Tobago`,`tt`,`1868`],[`Tunisia`,`tn`,`216`],[`Turkey`,`tr`,`90`,`... ... .. ..`],[`Turkmenistan`,`tm`,`993`],[`Tuvalu`,`tv`,`688`],[`Uganda`,`ug`,`256`],[`Ukraine`,`ua`,`380`,`(..) ... .. ..`],[`United Arab Emirates`,`ae`,`971`,{default:`.. ... ....`,"/^5[024568]/":`.. ... ....`,"/^[234679]/":`. ... ....`}],[`United Kingdom`,`gb`,`44`,`.... ......`],[`United States`,`us`,`1`,`(...) ...-....`,0],[`Uruguay`,`uy`,`598`],[`Uzbekistan`,`uz`,`998`,`.. ... .. ..`],[`Vanuatu`,`vu`,`678`],[`Vatican City`,`va`,`39`,`.. .... ....`,1],[`Venezuela`,`ve`,`58`],[`Vietnam`,`vn`,`84`],[`Wallis & Futuna`,`wf`,`681`,`.. .. ..`],[`Yemen`,`ye`,`967`],[`Zambia`,`zm`,`260`],[`Zimbabwe`,`zw`,`263`]],a=`react-international-phone-`,o=(...e)=>e.filter(e=>!!e).join(` `).trim(),s=(...e)=>o(...e).split(` `).map(e=>`${a}${e}`).join(` `),c=({addPrefix:e,rawClassNames:t})=>o(s(...e),...t),l=({value:e,mask:t,maskSymbol:n,offset:r=0,trimNonMaskCharsLeftover:i=!1,allowMaskOverflow:a=!1})=>{if(e.length<r)return e;let o=e.slice(0,r),s=e.slice(r),c=t.split(``).filter(e=>e===n).length,l=s.slice(0,c),u=a?s.slice(c):``,d=o,f=0;for(let e of t.split(``)){if(f>=l.length){if(!i&&e!==n){d+=e;continue}break}e===n?(d+=l[f],f+=1):d+=e}return d+u},u=e=>e?/^\d+$/.test(e):!1,d=e=>e.replace(/\D/g,``),f=(e,t)=>{let n=e.style.display;n!==`block`&&(e.style.display=`block`);let r=e.getBoundingClientRect(),i=t.getBoundingClientRect(),a=i.top-r.top,o=r.bottom-i.bottom;a>=0&&o>=0||(Math.abs(a)<Math.abs(o)?e.scrollTop+=a:e.scrollTop-=o),e.style.display=n},p=()=>typeof window>`u`?!1:window.navigator.userAgent.toLowerCase().includes(`macintosh`),m=(e,t)=>{let n=t.disableDialCodeAndPrefix?!1:t.forceDialCode,r=t.disableDialCodeAndPrefix?!1:t.insertDialCodeOnEmpty,i=e,a=e=>t.trimNonDigitsEnd?e.trim():e;if(!i)return r&&!i.length||n?a(`${t.prefix}${t.dialCode}${t.charAfterDialCode}`):a(i);if(i=d(i),i===t.dialCode&&!t.disableDialCodeAndPrefix)return a(`${t.prefix}${t.dialCode}${t.charAfterDialCode}`);if(t.dialCode.startsWith(i)&&!t.disableDialCodeAndPrefix)return a(n?`${t.prefix}${t.dialCode}${t.charAfterDialCode}`:`${t.prefix}${i}`);if(!i.startsWith(t.dialCode)&&!t.disableDialCodeAndPrefix){if(n)return a(`${t.prefix}${t.dialCode}${t.charAfterDialCode}`);if(i.length<t.dialCode.length)return a(`${t.prefix}${i}`)}let{phoneLeftSide:o,phoneRightSide:s}=(()=>{let e=t.dialCode.length;return{phoneLeftSide:i.slice(0,e),phoneRightSide:i.slice(e)}})();return o=`${t.prefix}${o}${t.charAfterDialCode}`,s=l({value:s,mask:t.mask,maskSymbol:t.maskChar,trimNonMaskCharsLeftover:t.trimNonDigitsEnd||t.disableDialCodeAndPrefix&&s.length===0,allowMaskOverflow:t.allowMaskOverflow}),t.disableDialCodeAndPrefix&&(o=``),a(`${o}${s}`)},h=({phoneBeforeInput:e,phoneAfterInput:t,phoneAfterFormatted:n,cursorPositionAfterInput:r,leftOffset:i=0,deletion:a})=>{if(r<i)return i;if(!e)return n.length;let o=null;for(let e=r-1;e>=0;--e)if(u(t[e])){o=e;break}if(o===null){for(let e=0;e<t.length;e+=1)if(u(n[e]))return e;return t.length}let s=0;for(let e=0;e<o;e+=1)u(t[e])&&(s+=1);let c=0,l=0;for(let e=0;e<n.length&&(c+=1,u(n[e])&&(l+=1),!(l>=s+1));e+=1);if(a!==`backward`)for(;!u(n[c])&&c<n.length;)c+=1;return c},g=({phone:e,prefix:t})=>e?`${t}${d(e)}`:``;function _({value:e,country:t,insertDialCodeOnEmpty:n,trimNonDigitsEnd:r,countries:i,prefix:a,charAfterDialCode:o,forceDialCode:s,disableDialCodeAndPrefix:c,defaultMask:l,countryGuessingEnabled:u,disableFormatting:d,allowMaskOverflow:f}){let p=e;c&&(p=p.startsWith(`${a}`)?p:`${a}${t.dialCode}${p}`);let h=u?j({phone:p,countries:i,currentCountryIso2:t?.iso2}):void 0,_=h?.country??t,v=m(p,{prefix:a,mask:D({phone:p,country:_,defaultMask:l,disableFormatting:d}),maskChar:w,dialCode:_.dialCode,trimNonDigitsEnd:r,charAfterDialCode:o,forceDialCode:s,insertDialCodeOnEmpty:n,disableDialCodeAndPrefix:c,allowMaskOverflow:f}),y=u&&!h?.fullDialCodeMatch?t:_;return{phone:g({phone:c?`${y.dialCode}${v}`:v,prefix:a}),inputValue:v,country:y}}var v=e=>{if(e?.toLocaleLowerCase().includes(`delete`)??!1)return e?.toLocaleLowerCase().includes(`forward`)?`forward`:`backward`},y=(e,{country:t,insertDialCodeOnEmpty:n,phoneBeforeInput:r,prefix:i,charAfterDialCode:a,forceDialCode:o,disableDialCodeAndPrefix:s,countryGuessingEnabled:c,defaultMask:l,disableFormatting:d,countries:f,allowMaskOverflow:p})=>{let m=e.nativeEvent,y=m.inputType,b=v(y),x=!!y?.startsWith(`insertFrom`),S=y===`insertText`,C=m?.data||void 0,w=e.target.value,T=e.target.selectionStart??0;if(y?.includes(`history`))return{inputValue:r,phone:g({phone:r,prefix:i}),cursorPosition:r.length,country:t};if(S&&!u(C)&&w!==i)return{inputValue:r,phone:g({phone:s?`${t.dialCode}${r}`:r,prefix:i}),cursorPosition:T-(C?.length??0),country:t};if(o&&!w.startsWith(`${i}${t.dialCode}`)&&!x){let e=w?r:`${i}${t.dialCode}${a}`;return{inputValue:e,phone:g({phone:e,prefix:i}),cursorPosition:i.length+t.dialCode.length+a.length,country:t}}let{phone:E,inputValue:D,country:O}=_({value:w,country:t,trimNonDigitsEnd:b===`backward`,insertDialCodeOnEmpty:n,countryGuessingEnabled:c,countries:f,prefix:i,charAfterDialCode:a,forceDialCode:o,disableDialCodeAndPrefix:s,disableFormatting:d,defaultMask:l,allowMaskOverflow:p});return{phone:E,inputValue:D,cursorPosition:h({cursorPositionAfterInput:T,phoneBeforeInput:r,phoneAfterInput:w,phoneAfterFormatted:D,leftOffset:o?i.length+t.dialCode.length+a.length:0,deletion:b}),country:O}},b=(e,t)=>{let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return!1;for(let r of n)if(e[r]!==t[r])return!1;return!0},x=()=>{let e=(0,r.useRef)(),t=(0,r.useRef)(Date.now()),n=(0,r.useCallback)(()=>{let n=Date.now(),r=e.current?n-t.current:void 0;return e.current=t.current,t.current=n,r},[]);return(0,r.useMemo)(()=>({check:n}),[n])},S={size:20,overrideLastItemDebounceMS:-1};function C(e,t){let{size:n,overrideLastItemDebounceMS:i,onChange:a}={...S,...t},[o,s]=(0,r.useState)(e),c=(0,r.useRef)([o]),l=(0,r.useRef)(0),u=x();return[o,(0,r.useCallback)((e,t)=>{let r=c.current[l.current];if(e===r||typeof e==`object`&&typeof r==`object`&&b(e,r))return;let o=i>0,d=u.check(),f=o&&d!==void 0?d>i:!0;if(t?.overrideLastItem===void 0?!f:t.overrideLastItem)c.current=[...c.current.slice(0,l.current),e];else{let t=c.current.length>=n;c.current=[...c.current.slice(+!!t,l.current+1),e],t||(l.current+=1)}s(e),a?.(e)},[a,i,n,u]),(0,r.useCallback)(()=>{if(l.current<=0)return{success:!1};let e=c.current[l.current-1];return s(e),--l.current,a?.(e),{success:!0,value:e}},[a]),(0,r.useCallback)(()=>{if(l.current+1>=c.current.length)return{success:!1};let e=c.current[l.current+1];return s(e),l.current+=1,a?.(e),{success:!0,value:e}},[a])]}var w=`.`,T={defaultCountry:`us`,value:``,prefix:`+`,defaultMask:`............`,charAfterDialCode:` `,historySaveDebounceMS:200,disableCountryGuess:!1,disableDialCodePrefill:!1,forceDialCode:!1,disableDialCodeAndPrefix:!1,disableFormatting:!1,allowMaskOverflow:!1,countries:i,preferredCountries:[]},E=({defaultCountry:e=T.defaultCountry,value:t=T.value,countries:n=T.countries,prefix:i=T.prefix,defaultMask:a=T.defaultMask,charAfterDialCode:o=T.charAfterDialCode,historySaveDebounceMS:s=T.historySaveDebounceMS,disableCountryGuess:c=T.disableCountryGuess,disableDialCodePrefill:l=T.disableDialCodePrefill,forceDialCode:u=T.forceDialCode,disableDialCodeAndPrefix:d=T.disableDialCodeAndPrefix,disableFormatting:f=T.disableFormatting,allowMaskOverflow:m=T.allowMaskOverflow,onChange:h,inputRef:g})=>{let v={countries:n,prefix:i,charAfterDialCode:o,forceDialCode:d?!1:u,disableDialCodeAndPrefix:d,defaultMask:a,countryGuessingEnabled:!c,disableFormatting:f,allowMaskOverflow:m},b=(0,r.useRef)(null),x=g||b,S=e=>{Promise.resolve().then(()=>{typeof window>`u`||x.current!==document?.activeElement||x.current?.setSelectionRange(e,e)})},w=(0,r.useCallback)(e=>A({value:e,field:`iso2`,countries:n}),[n]),[{phone:E,inputValue:D,country:O},k,j,M]=C(()=>{let r=A({value:e,field:`iso2`,countries:n});r||console.error(`[react-international-phone]: can not find a country with "${e}" iso2 code`);let{phone:i,inputValue:a,country:o}=_({value:t,country:r||A({value:`us`,field:`iso2`,countries:n}),insertDialCodeOnEmpty:!l,...v});return S(a.length),{phone:i,inputValue:a,country:o.iso2}},{overrideLastItemDebounceMS:s,onChange:(0,r.useCallback)(({inputValue:e,phone:t,country:n})=>{h&&h({phone:t,inputValue:e,country:w(n)})},[w,h])}),N=(0,r.useMemo)(()=>w(O),[O,w]);(0,r.useEffect)(()=>{let e=x.current;if(!e)return;let t=e=>{if(!e.key)return;let t=e.ctrlKey,n=e.metaKey,r=e.shiftKey;if(e.key.toLowerCase()===`z`){if(p()){if(!n)return}else if(!t)return;r?M():j()}};return e.addEventListener(`keydown`,t),()=>{e.removeEventListener(`keydown`,t)}},[x,j,M]);let P=e=>{e.preventDefault();let{phone:n,inputValue:r,country:i,cursorPosition:a}=y(e,{country:N,phoneBeforeInput:D,insertDialCodeOnEmpty:!1,...v});return k({inputValue:r,phone:n,country:i.iso2}),S(a),t},F=(0,r.useCallback)((e,t={focusOnInput:!1})=>{let r=A({value:e,field:`iso2`,countries:n});if(!r){console.error(`[react-international-phone]: can not find a country with "${e}" iso2 code`);return}k({inputValue:d?``:`${i}${r.dialCode}${o}`,phone:`${i}${r.dialCode}`,country:r.iso2}),t.focusOnInput&&Promise.resolve().then(()=>{x.current?.focus()})},[n,d,i,o,k,x]),[I,L]=(0,r.useState)(!1);return(0,r.useEffect)(()=>{if(!I){L(!0),t!==E&&h?.({inputValue:D,phone:E,country:N});return}if(t===E)return;let{phone:e,inputValue:n,country:r}=_({value:t,country:N,insertDialCodeOnEmpty:!l,...v});k({phone:e,inputValue:n,country:r.iso2})},[t]),{phone:E,inputValue:D,country:N,setCountry:F,handlePhoneValueChange:P,inputRef:x}},D=({phone:e,country:t,defaultMask:n=`............`,disableFormatting:r=!1})=>{let i=t.format,a=e=>r?e.replace(RegExp(`[^${w}]`,`g`),``):e;if(!i)return a(n);if(typeof i==`string`)return a(i);if(!i.default)return console.error(`[react-international-phone]: default mask for ${t.iso2} is not provided`),a(n);let o=Object.keys(i).find(n=>{if(n===`default`)return!1;if(!(n.charAt(0)===`/`&&n.charAt(n.length-1)===`/`))return console.error(`[react-international-phone]: format regex "${n}" for ${t.iso2} is not valid`),!1;let r=new RegExp(n.substring(1,n.length-1)),i=e.replace(t.dialCode,``);return r.test(d(i))});return a(o?i[o]:i.default)},O=e=>{let[t,n,r,i,a,o]=e;return{name:t,iso2:n,dialCode:r,format:i,priority:a,areaCodes:o}},k=e=>`Field "${e}" is not supported`,A=({field:e,value:t,countries:n=i})=>{if([`priority`].includes(e))throw Error(k(e));let r=n.find(n=>t===O(n)[e]);if(r)return O(r)},j=({phone:e,countries:t=i,currentCountryIso2:n})=>{let r={country:void 0,fullDialCodeMatch:!1};if(!e)return r;let a=d(e);if(!a)return r;let o=r,s=({country:e,fullDialCodeMatch:t})=>{let n=e.dialCode===o.country?.dialCode,r=(e.priority??0)<(o.country?.priority??0);(!n||r)&&(o={country:e,fullDialCodeMatch:t})};for(let e of t){let t=O(e),{dialCode:n,areaCodes:r}=t;if(a.startsWith(n)){let e=o.country?Number(n)>=Number(o.country.dialCode):!0;if(r){let e=a.substring(n.length);for(let n of r)if(e.startsWith(n))return{country:t,fullDialCodeMatch:!0}}(e||n===a||!o.fullDialCodeMatch)&&s({country:t,fullDialCodeMatch:!0})}o.fullDialCodeMatch||a.length<n.length&&n.startsWith(a)&&(!o.country||Number(n)<=Number(o.country.dialCode))&&s({country:t,fullDialCodeMatch:!1})}if(n){let e=A({value:n,field:`iso2`,countries:t});if(!e)return o;let r=e?(e=>{if(!e?.areaCodes)return!1;let t=a.substring(e.dialCode.length);return e.areaCodes.some(e=>e.startsWith(t))})(e):!1;o&&o.country?.dialCode===e.dialCode&&o.country!==e&&o.fullDialCodeMatch&&(!e.areaCodes||r)&&(o={country:e,fullDialCodeMatch:!0})}return o},M=(e,t)=>Number(parseInt(e,16)+t).toString(16),N=`abcdefghijklmnopqrstuvwxyz`,P=`1f1e6`,F=N.split(``).reduce((e,t,n)=>({...e,[t]:M(P,n)}),{}),I=e=>[F[e[0]],F[e[1]]].join(`-`),L=({iso2:e,size:t,src:n,protocol:i=`https`,disableLazyLoading:a,className:o,style:s,...l})=>e?r.createElement(`img`,{className:c({addPrefix:[`flag-emoji`],rawClassNames:[o]}),src:n||`${i}://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/svg/${I(e)}.svg`,width:t,height:t,draggable:!1,"data-country":e,loading:a?void 0:`lazy`,style:{width:t,height:t,...s},alt:``,...l}):r.createElement(`img`,{className:c({addPrefix:[`flag-emoji`],rawClassNames:[o]}),width:t,height:t,...l}),R=1e3,z=({show:e,dialCodePrefix:t=`+`,selectedCountry:n,countries:a=i,preferredCountries:o=[],flags:s,onSelect:l,onClose:u,...d})=>{let p=(0,r.useRef)(null),m=(0,r.useRef)(),h=(0,r.useMemo)(()=>{if(!o||!o.length)return a;let e=[],t=[...a];for(let n of o){let r=t.findIndex(e=>O(e).iso2===n);if(r!==-1){let n=t.splice(r,1)[0];e.push(n)}}return e.concat(t)},[a,o]),g=(0,r.useRef)({updatedAt:void 0,value:``}),_=e=>{g.current={value:g.current.updatedAt&&new Date().getTime()-g.current.updatedAt.getTime()>R?e:`${g.current.value}${e}`,updatedAt:new Date};let t=h.findIndex(e=>O(e).name.toLowerCase().startsWith(g.current.value));t!==-1&&b(t)},v=(0,r.useCallback)(e=>h.findIndex(t=>O(t).iso2===e),[h]),[y,b]=(0,r.useState)(v(n)),x=()=>{m.current!==n&&b(v(n))},S=(0,r.useCallback)(e=>{b(v(e.iso2)),l?.(e)},[l,v]),C=e=>{let t=h.length-1,n=n=>e===`prev`?n-1:e===`next`?n+1:e===`last`?t:0;b(e=>{let r=n(e);return r<0?0:r>t?t:r})},w=e=>{if(e.stopPropagation(),e.key===`Enter`){e.preventDefault(),S(O(h[y]));return}if(e.key===`Escape`){u?.();return}if(e.key===`ArrowUp`){e.preventDefault(),C(`prev`);return}if(e.key===`ArrowDown`){e.preventDefault(),C(`next`);return}if(e.key===`PageUp`){e.preventDefault(),C(`first`);return}if(e.key===`PageDown`){e.preventDefault(),C(`last`);return}e.key===` `&&e.preventDefault(),e.key.length===1&&!e.altKey&&!e.ctrlKey&&!e.metaKey&&_(e.key.toLocaleLowerCase())},T=(0,r.useCallback)(()=>{if(!p.current||y===void 0)return;let e=O(h[y]).iso2;if(e===m.current)return;let t=p.current.querySelector(`[data-country="${e}"]`);t&&(f(p.current,t),m.current=e)},[y,h]);return(0,r.useEffect)(()=>{T()},[y,T]),(0,r.useEffect)(()=>{p.current&&(e?p.current.focus():x())},[e]),(0,r.useEffect)(()=>{x()},[n]),r.createElement(`ul`,{ref:p,role:`listbox`,className:c({addPrefix:[`country-selector-dropdown`],rawClassNames:[d.className]}),style:{display:e?`block`:`none`,...d.style},onKeyDown:w,onBlur:u,tabIndex:-1,"aria-activedescendant":`react-international-phone__${O(h[y]).iso2}-option`},h.map((e,i)=>{let a=O(e),l=a.iso2===n,u=i===y,f=o.includes(a.iso2),p=i===o.length-1,m=s?.find(e=>e.iso2===a.iso2);return r.createElement(r.Fragment,{key:a.iso2},r.createElement(`li`,{"data-country":a.iso2,role:`option`,"aria-selected":l,"aria-label":`${a.name} ${t}${a.dialCode}`,id:`react-international-phone__${a.iso2}-option`,className:c({addPrefix:[`country-selector-dropdown__list-item`,f&&`country-selector-dropdown__list-item--preferred`,l&&`country-selector-dropdown__list-item--selected`,u&&`country-selector-dropdown__list-item--focused`],rawClassNames:[d.listItemClassName,f&&d.listItemPreferredClassName,l&&d.listItemSelectedClassName,u&&d.listItemFocusedClassName]}),onClick:()=>S(a),style:d.listItemStyle,title:a.name},r.createElement(L,{iso2:a.iso2,src:m?.src,className:c({addPrefix:[`country-selector-dropdown__list-item-flag-emoji`],rawClassNames:[d.listItemFlagClassName]}),style:d.listItemFlagStyle}),r.createElement(`span`,{className:c({addPrefix:[`country-selector-dropdown__list-item-country-name`],rawClassNames:[d.listItemCountryNameClassName]}),style:d.listItemCountryNameStyle},a.name),r.createElement(`span`,{className:c({addPrefix:[`country-selector-dropdown__list-item-dial-code`],rawClassNames:[d.listItemDialCodeClassName]}),style:d.listItemDialCodeStyle},t,a.dialCode)),p?r.createElement(`hr`,{className:c({addPrefix:[`country-selector-dropdown__preferred-list-divider`],rawClassNames:[d.preferredListDividerClassName]}),style:d.preferredListDividerStyle}):null)}))},B=r.memo(({selectedCountry:e,onSelect:t,disabled:n,hideDropdown:a,countries:o=i,preferredCountries:s=[],flags:l,renderButtonWrapper:u,...d})=>{let[f,p]=(0,r.useState)(!1),m=(0,r.useMemo)(()=>{if(e)return A({value:e,field:`iso2`,countries:o})},[o,e]),h=(0,r.useRef)(null),g=e=>{e.key&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&(e.preventDefault(),p(!0))};return r.createElement(`div`,{className:c({addPrefix:[`country-selector`],rawClassNames:[d.className]}),style:d.style,ref:h},(()=>{let t={title:m?.name,onClick:()=>p(e=>!e),onMouseDown:e=>e.preventDefault(),onKeyDown:g,disabled:a||n,role:`combobox`,"aria-label":`Country selector`,"aria-haspopup":`listbox`,"aria-expanded":f},i=r.createElement(`div`,{className:c({addPrefix:[`country-selector-button__button-content`],rawClassNames:[d.buttonContentWrapperClassName]}),style:d.buttonContentWrapperStyle},r.createElement(L,{iso2:e,src:l?.find(t=>t.iso2===e)?.src,className:c({addPrefix:[`country-selector-button__flag-emoji`,n&&`country-selector-button__flag-emoji--disabled`],rawClassNames:[d.flagClassName]}),style:{visibility:e?`visible`:`hidden`,...d.flagStyle}}),!a&&r.createElement(`div`,{className:c({addPrefix:[`country-selector-button__dropdown-arrow`,n&&`country-selector-button__dropdown-arrow--disabled`,f&&`country-selector-button__dropdown-arrow--active`],rawClassNames:[d.dropdownArrowClassName]}),style:d.dropdownArrowStyle}));return u?u({children:i,rootProps:t}):r.createElement(`button`,{...t,type:`button`,className:c({addPrefix:[`country-selector-button`,f&&`country-selector-button--active`,n&&`country-selector-button--disabled`,a&&`country-selector-button--hide-dropdown`],rawClassNames:[d.buttonClassName]}),"data-country":e,style:d.buttonStyle},i)})(),r.createElement(z,{show:f,countries:o,preferredCountries:s,flags:l,onSelect:e=>{p(!1),t?.(e)},selectedCountry:e,onClose:()=>{p(!1)},...d.dropdownStyleProps}))}),V=({dialCode:e,prefix:t,disabled:n,style:i,className:a})=>r.createElement(`div`,{className:c({addPrefix:[`dial-code-preview`,n&&`dial-code-preview--disabled`],rawClassNames:[a]}),style:i},`${t}${e}`),H=(0,r.forwardRef)(({value:e,onChange:t,countries:n=i,preferredCountries:a,hideDropdown:o,showDisabledDialCodeAndPrefix:s,disableFocusAfterCountrySelect:l,flags:u,style:d,className:f,inputStyle:p,inputClassName:m,countrySelectorStyleProps:h,dialCodePreviewStyleProps:g,inputProps:_,placeholder:v,disabled:y,name:b,onFocus:x,onBlur:S,required:C,autoFocus:w,...T},D)=>{let O=(0,r.useCallback)(e=>{t?.(e.phone,{country:e.country,inputValue:e.inputValue})},[t]),{phone:k,inputValue:A,inputRef:j,country:M,setCountry:N,handlePhoneValueChange:P}=E({value:e,countries:n,...T,onChange:O}),F=T.disableDialCodeAndPrefix&&s&&M?.dialCode,I=(0,r.useCallback)(e=>{N(e.iso2,{focusOnInput:!l})},[N,l]);return(0,r.useImperativeHandle)(D,()=>j.current?Object.assign(j.current,{setCountry:N,state:{phone:k,inputValue:A,country:M}}):null,[j,N,k,A,M]),r.createElement(`div`,{ref:D,className:c({addPrefix:[`input-container`],rawClassNames:[f]}),style:d},r.createElement(B,{onSelect:I,flags:u,selectedCountry:M?.iso2,countries:n,preferredCountries:a,disabled:y,hideDropdown:o,...h}),F&&r.createElement(V,{dialCode:M.dialCode,prefix:T.prefix??`+`,disabled:y,...g}),r.createElement(`input`,{onChange:P,value:A,type:`tel`,ref:j,className:c({addPrefix:[`input`,y&&`input--disabled`],rawClassNames:[m]}),placeholder:v,disabled:y,style:p,name:b,onFocus:x,onBlur:S,autoFocus:w,required:C,..._}))}),U=n(),W=[`us`,`gb`,`ca`,`au`,`nz`,`ie`,`ae`,`sg`],G=[...i.filter(e=>W.includes(e[1])),...i.filter(e=>!W.includes(e[1]))];function K({field:e,value:t,onChange:n}){return(0,U.jsxs)(`div`,{className:`flex flex-col w-full relative z-[99999]`,children:[(0,U.jsxs)(`label`,{className:`text-[13px] font-medium text-foreground/50 select-none mb-1.5 ml-1`,children:[e.label,` `,e.required&&(0,U.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,U.jsx)(H,{defaultCountry:`us`,countries:G,value:t,onChange:e=>n(e),forceDialCode:!0,className:`w-full flex items-center rounded-xl text-[15px] text-foreground transition-all duration-300 focus-within:border-accent glow-focus glass-panel overflow-visible relative h-12`,inputClassName:`flex-1 w-full !bg-transparent !border-none !outline-none !shadow-none px-3 text-[15px] text-foreground m-0 p-0 h-full tracking-[0.5px] no-glow`,countrySelectorStyleProps:{buttonClassName:`!bg-transparent !border-0 border-r !border-[var(--panel-border)]/50 !outline-none !shadow-none !px-3 hover:!bg-foreground/5 transition-colors h-full !rounded-xl !rounded-r-none flex items-center justify-center shrink-0`}})]})}export{K as default};
@@ -0,0 +1 @@
1
+ .react-international-phone-country-selector{position:relative}.react-international-phone-country-selector-button{height:var(--react-international-phone-height,36px);box-sizing:border-box;border:1px solid var(--react-international-phone-country-selector-border-color,var(--react-international-phone-border-color,gainsboro));appearance:button;background-color:var(--react-international-phone-country-selector-background-color,var(--react-international-phone-background-color,white));cursor:pointer;text-transform:none;-webkit-user-select:none;user-select:none;justify-content:center;align-items:center;margin:0;padding:0;display:flex}.react-international-phone-country-selector-button:hover{background-color:var(--react-international-phone-country-selector-background-color-hover,whitesmoke)}.react-international-phone-country-selector-button--hide-dropdown{cursor:auto}.react-international-phone-country-selector-button--hide-dropdown:hover{background-color:#0000}.react-international-phone-country-selector-button__button-content{justify-content:center;align-items:center;display:flex}.react-international-phone-country-selector-button__flag-emoji{margin:0 4px}.react-international-phone-country-selector-button__flag-emoji--disabled{opacity:.75}.react-international-phone-country-selector-button__dropdown-arrow{border-top:var(--react-international-phone-country-selector-arrow-size,4px) solid var(--react-international-phone-country-selector-arrow-color,#777);border-right:var(--react-international-phone-country-selector-arrow-size,4px) solid transparent;border-left:var(--react-international-phone-country-selector-arrow-size,4px) solid transparent;margin-right:4px;transition:all .1s ease-out}.react-international-phone-country-selector-button__dropdown-arrow--active{transform:rotateX(180deg)}.react-international-phone-country-selector-button__dropdown-arrow--disabled{border-top-color:var(--react-international-phone-disabled-country-selector-arrow-color,#999)}.react-international-phone-country-selector-button--disabled,.react-international-phone-country-selector-button--disabled:hover{background-color:var(--react-international-phone-disabled-country-selector-background-color,var(--react-international-phone-disabled-background-color,whitesmoke))}.react-international-phone-country-selector-button--disabled{cursor:auto}.react-international-phone-flag-emoji{width:var(--react-international-phone-flag-width,24px);height:var(--react-international-phone-flag-height,24px);box-sizing:border-box}.react-international-phone-country-selector-dropdown{z-index:1;top:var(--react-international-phone-dropdown-top,44px);left:var(--react-international-phone-dropdown-left,0);background-color:var(--react-international-phone-dropdown-item-background-color,var(--react-international-phone-background-color,white));width:300px;max-height:200px;box-shadow:var(--react-international-phone-dropdown-shadow,2px 2px 16px #00000040);color:var(--react-international-phone-dropdown-item-text-color,var(--react-international-phone-text-color,#222));flex-direction:column;margin:0;padding:4px 0;list-style:none;display:flex;position:absolute;overflow-y:scroll}.react-international-phone-country-selector-dropdown__preferred-list-divider{height:1px;margin:var(--react-international-phone-dropdown-preferred-list-divider-margin,0);background:var(--react-international-phone-dropdown-preferred-list-divider-color,var(--react-international-phone-border-color,gainsboro));border:none}.react-international-phone-country-selector-dropdown__list-item{min-height:var(--react-international-phone-dropdown-item-height,28px);box-sizing:border-box;align-items:center;padding:2px 8px;display:flex}.react-international-phone-country-selector-dropdown__list-item-flag-emoji{margin-right:8px}.react-international-phone-country-selector-dropdown__list-item-country-name{font-size:var(--react-international-phone-dropdown-item-font-size,14px);text-overflow:ellipsis;white-space:nowrap;margin-right:8px;overflow:hidden}.react-international-phone-country-selector-dropdown__list-item-dial-code{color:var(--react-international-phone-dropdown-item-dial-code-color,gray);font-size:var(--react-international-phone-dropdown-item-font-size,14px)}.react-international-phone-country-selector-dropdown__list-item:hover{background-color:var(--react-international-phone-selected-dropdown-item-background-color,var(--react-international-phone-selected-dropdown-item-background-color,whitesmoke));cursor:pointer}.react-international-phone-country-selector-dropdown__list-item--selected,.react-international-phone-country-selector-dropdown__list-item--focused{background-color:var(--react-international-phone-selected-dropdown-item-background-color,whitesmoke);color:var(--react-international-phone-selected-dropdown-item-text-color,var(--react-international-phone-text-color,#222))}.react-international-phone-country-selector-dropdown__list-item--selected .react-international-phone-country-selector-dropdown__list-item-dial-code,.react-international-phone-country-selector-dropdown__list-item--focused .react-international-phone-country-selector-dropdown__list-item-dial-code{color:var(--react-international-phone-selected-dropdown-item-dial-code-color,var(--react-international-phone-dropdown-item-dial-code-color,gray))}.react-international-phone-country-selector-dropdown__list-item--focused{background-color:var(--react-international-phone-selected-dropdown-item-background-color,var(--react-international-phone-selected-dropdown-item-background-color,whitesmoke))}.react-international-phone-dial-code-preview{border:1px solid var(--react-international-phone-dial-code-preview-border-color,var(--react-international-phone-border-color,gainsboro));background-color:var(--react-international-phone-dial-code-preview-background-color,var(--react-international-phone-background-color,white));color:var(--react-international-phone-dial-code-preview-text-color,var(--react-international-phone-text-color,#222));font-size:var(--react-international-phone-dial-code-preview-font-size,var(--react-international-phone-font-size,13px));justify-content:center;align-items:center;margin-right:-1px;padding:0 8px;display:flex}.react-international-phone-dial-code-preview--disabled{background-color:var(--react-international-phone-dial-code-preview-disabled-background-color,var(--react-international-phone-disabled-background-color,whitesmoke));color:var(--react-international-phone-dial-code-preview-disabled-text-color,var(--react-international-phone-disabled-text-color,#666))}.react-international-phone-input-container{display:flex}.react-international-phone-input-container .react-international-phone-country-selector-button{border-radius:var(--react-international-phone-border-radius,4px);border-top-right-radius:0;border-bottom-right-radius:0;margin-right:-1px}.react-international-phone-input-container .react-international-phone-input{height:var(--react-international-phone-height,36px);box-sizing:border-box;border:1px solid var(--react-international-phone-border-color,gainsboro);border-radius:var(--react-international-phone-border-radius,4px);background-color:var(--react-international-phone-background-color,white);color:var(--react-international-phone-text-color,#222);font-family:inherit;font-size:var(--react-international-phone-font-size,13px);border-top-left-radius:0;border-bottom-left-radius:0;margin:0;padding:0 8px;overflow:visible}.react-international-phone-input-container .react-international-phone-input:focus{outline:none}.react-international-phone-input-container .react-international-phone-input--disabled{background-color:var(--react-international-phone-disabled-background-color,whitesmoke);color:var(--react-international-phone-disabled-text-color,#666)}
@@ -1,4 +1,4 @@
1
- require(`./chunk-DYteiM-1.cjs`);var e=`<!-- generated by your-ai-workflow-firebase-os v1.11.1 -->
1
+ var e=`<!-- generated by your-ai-workflow-firebase-os v1.13.0 -->
2
2
  # Working in this project
3
3
 
4
4
  This app is powered by Your AI Firebase β€” the \`<FirebaseOS />\` component. The
@@ -64,10 +64,13 @@ change the owner can use and a change they cannot.
64
64
  7. A page the owner added on their Pages screen ALREADY EXISTS. The sentence
65
65
  they paste says so, names its web address and names its one content file β€”
66
66
  write exactly that file plus its two registry.ts lines (and, only when the
67
- sentence asks for the page's own form, that one named \`*Form.config.ts\`)
68
- and NOTHING else: no page config file, no second address, nothing to
69
- Firestore, and never a reply
70
- telling them to create or fix anything. Only a page asked for in the chat,
67
+ sentence asks for the page's own form, that one named \`*Form.config.ts\` β€”
68
+ unless the owner's words in it name a form the app already has, which you
69
+ show instead of making another) and NOTHING else: no page config file, no
70
+ second address, nothing to Firestore, and never a reply telling them to
71
+ create or fix anything. Whatever that sentence leaves undecided β€” section
72
+ titles, button words, layout, where the pictures and the form go β€” decide
73
+ yourself and build it finished; never stop to ask. Only a page asked for in the chat,
71
74
  one that exists nowhere yet, is YOURS to create, and then it is created as
72
75
  FILES β€” never in Firestore: its config file and its content file, both
73
76
  named from the page's name β€” a page called "Client onboarding" is
@@ -155,14 +158,23 @@ change the owner can use and a change they cannot.
155
158
  for ANYTHING RECURRING β€” a subscription always uses a price id the owner
156
159
  made in Stripe (their Payments screen shows it with a copy button), never
157
160
  a typed amount, and the server refuses one without it. Payments ARRIVE
158
- inside a page's own sentence from the Pages screen: the owner describes
159
- what they sell on their Payments screen, attaches it to a page under
160
- Payments on this page, and that page's sentence carries the exact
161
- \`<PayButton>\` tags with their ids or amounts, what the buyer says first,
162
- what happens after and what the owner wants on the page β€” build exactly
163
- that, on exactly that page, and nothing more. The button draws
164
- nothing until the owner has connected Stripe, so it is always safe to
165
- place. What the signed-in person has bought is read with
161
+ as ONE request from the owner's Payments screen: they describe what they
162
+ sell there, say how each payment works, tick β€” for each payment β€” the
163
+ pages IT goes on under Wire it into your pages, say what should appear
164
+ there or name a page to add, and paste a request that carries the exact
165
+ \`<PayButton>\` tags with their ids or amounts, how each payment works in
166
+ their words, which pages each one goes on, each such page with its one
167
+ content file, the owner's words on it, and
168
+ the way THIS app makes a page, a form and a link β€” build exactly that,
169
+ on exactly those pages, the app's way, and nothing more. Whatever that
170
+ request leaves undecided β€” what the buyer is asked first, what they see
171
+ after paying, what a plan unlocks, the layout β€” decide yourself and build
172
+ it finished; never stop to ask. A payment asked for in the chat instead
173
+ gets the same button, on the page they name, and you ask for the one
174
+ thing you cannot invent β€” a price id for anything recurring, an amount
175
+ and a name for a one-off β€” only when they have not given it. The button draws
176
+ nothing until the owner has connected Stripe and has the Take payments
177
+ switch on the Payments screen on, so it is always safe to place. What the signed-in person has bought is read with
166
178
  \`useMyPayments()\` from the same package β€” it returns \`{ loading, active,
167
179
  subscriptions, payments }\` and \`active\` is true while any subscription
168
180
  is live. On an INTERNAL page the owner's team reads every sale with
@@ -246,13 +258,19 @@ change the owner can use and a change they cannot.
246
258
  that names a \`mem_\`, \`admin_\` or \`user_\` collection.
247
259
  12. NEVER build a calendar, a time picker, a list of free times or a bookings
248
260
  collection of your own. Booking is ONE form question β€” \`type: 'schedule'\`
249
- with \`members\` (the ids the owner's sentence gives you, copied exactly as
250
- they are) and \`look\` (\`'calendar'\` for a page that is about booking,
251
- \`'compact'\` for one question among others) β€” inside a \`*Form.config.ts\`
252
- shown with \`<ContactPopup formId="…" isInline />\`. The built-in form
261
+ with \`schedules\` (the ids the owner's sentence gives you, copied exactly
262
+ as they are β€” each names a kind of meeting on the owner's Schedule
263
+ screen, with its own length, hours and price, so never state or ask for
264
+ a length) and \`look\` (\`'calendar'\` for a page that is about booking,
265
+ \`'compact'\` for one question among others β€” your call, from the owner's
266
+ words on how booking should work) β€” inside a \`*Form.config.ts\` shown
267
+ with \`<ContactPopup formId="…" isInline />\`. The built-in form
253
268
  draws the picker, shows every visitor the free times in their own time
254
269
  zone, stops two people taking the same minute and lists every booking on
255
270
  the owner's Schedule screen; the entry lands in the Inbox like any other.
271
+ Every schedule also has a booking page of its own at \`/book/{id}\`, and
272
+ every one-time payment a page at \`/pay/{id}\` β€” both ship with the app
273
+ and are NEVER built, re-created or re-addressed.
256
274
  In the owner's own words: Booking goes through the app's own form system: the page's form gets ONE question of type 'schedule', and the built-in form draws the picker β€” never build a calendar, a time picker, a list of times or a bookings collection of your own. The app shows every visitor the free times in their own time zone, stops two people taking the same time, and lists every booking on my Schedule screen.
257
275
  On an INTERNAL or ADMIN page the team reads the bookings with
258
276
  \`useBookings()\` from \`'your-ai-workflow-firebase-os'\` β€” \`{ loading,
@@ -355,15 +373,16 @@ an empty page.
355
373
 
356
374
  | screen | web address | what they do there |
357
375
  | --------- | ------------- | ---------------------------------------------------------------------------------------------- |
358
- | Pages | \`/pages\` | add a page and its form, rename a page, change its web address or icon, reorder it, hide it, delete it; attach a payment to it and say what should happen there; choose the emails it sends and what about; link it to another page |
376
+ | Pages | \`/pages\` | add a page and its form, rename a page, change its web address or icon, reorder it, hide it, delete it; choose the emails it sends and what about; link it to another page. Payments are not attached here β€” the Payments screen wires them |
359
377
  | Forms | \`/forms\` | see every form; edit its title, questions and button text after it is built |
360
378
  | Inbox | \`/inbox\` | every form entry in one list, filtered "From anyone" or "From signed-in users" |
361
379
  | Theme | \`/theme\` | colours, corner rounding, the logo |
362
380
  | Users | \`/users\` | mark a person as Internal or Admin |
363
381
  | Assets | \`/assets\` | upload the public images the theme points at β€” admins only |
364
382
  | Guide | \`/guide\` | the walkthrough video, and sentences they can copy straight into this chat |
365
- | Payments | \`/payments\` | describe what they sell (prices and plans, under What you sell), then β€” under How your payments work β€” say how each payment works, what a buyer says first and what happens after; connect Stripe (via the payments switch on \`/setup\`), and see everyone who has paid β€” the money itself is a read-only mirror of Stripe. WHICH PAGE a payment lands on is decided on the Pages screen, never here |
366
- | Schedule | \`/schedule\` | set each team member's bookable hours in their own time zone β€” which days, from when to when, how long a booking lasts, how far ahead, how much notice β€” and see and cancel bookings. WHERE booking happens is decided on the Pages screen (Booking on this page) or on a form (a Pick-a-time question), never here |
383
+ | Payments | \`/payments\` | describe what they sell (things paid for once, each with a price, or plans and their Stripe ids, under What you sell), then β€” under How your payments work β€” say in one answer how each payment works, then β€” under Wire it into your pages β€” tick, for each payment, the pages it goes on, say what should appear there or name a page to add, and copy the ONE request that wires all of it (the request you receive); under Payment links, every one-time payment has a shipped page at \`/pay/{id}\` to send as a link, and Customise this page makes a real page on the Pages screen and hands you its sentence; connect Stripe (via the payments switch on \`/setup\`), and see everyone who has paid β€” the money itself is a read-only mirror of Stripe |
384
+ | Schedule | \`/schedule\` | make the schedules β€” one per kind of meeting a team member offers: its name, whose time it is, the bookable hours in their own time zone (which days, from when to when), how long a booking lasts, how far ahead, how much notice, a one-time payment taken first when they want one β€” and see and cancel bookings. Every schedule has a booking page of its own at \`/book/{id}\` the owner sends as a link. WHERE ELSE booking happens is decided on the Pages screen (Booking on this page) or on a form (a Pick-a-time question), never here |
385
+ | My calendar | \`/my-calendar\` | every team member's own: every booking made with them under every schedule of theirs, on a month grid, with Paid beside a booking that was paid for β€” it ships with the app, never build it |
367
386
  | Billing | \`/billing\` | their BUYERS' page, not theirs: a signed-in customer who has bought something finds what they bought and Stripe's manage-plan button here β€” it ships with the app, never build it |
368
387
  | Email | \`/email\` | connect email (via the email switch on \`/setup\`) and see what the app can do with it, and where owner mail goes β€” send history lives in Resend's own dashboard; WHICH emails a page sends is chosen on the Pages screen |
369
388
 
@@ -431,6 +450,12 @@ Each is filled by exactly one file, the same way as any other page:
431
450
  | Support | \`/support\` | \`microcomponents/SupportContent.tsx\` |
432
451
  | Dashboard | \`/dashboard\` | \`microcomponents/DashboardContent.tsx\` |
433
452
 
453
+ Two more pages ship with the app and have NO file to write: the booking page
454
+ of every schedule at \`/book/{id}\` and the payment page of every one-time
455
+ payment at \`/pay/{id}\`. The owner sends them as links; to link to one from a
456
+ page, use \`bookingPath(id)\` and \`payPath(id)\` from \`'your-ai-workflow-firebase-os'\`
457
+ with an id the owner's sentence gives you β€” never a path you made up.
458
+
434
459
  The dashboard is the screen a signed-in person lands on. It ships empty, and
435
460
  \`DashboardContent.tsx\` draws inside its panel, below the welcome heading and
436
461
  the dashboard menu the page already renders.
@@ -675,9 +700,11 @@ config file, no second address, and never a message back saying the page must
675
700
  be created first. It is already in their menu.
676
701
 
677
702
  That same row hands over a SECOND sentence once the page is built β€” one that
678
- says the content file "already exists" and asks for a change. Edit that one
679
- file in place, keep everything on the page they did not mention, and add
680
- nothing to registry.ts: the file is registered already.
703
+ says the content file "already exists" and asks for a change, in the owner's
704
+ own words and nothing else. Edit that one file in place β€” and the page's own
705
+ form where it is defined, when the change is about the form β€” keep everything
706
+ on the page they did not mention, and add nothing to registry.ts: the file is
707
+ registered already.
681
708
 
682
709
  CHECK FIRST β€” before you create anything. When the page they are talking
683
710
  about already has a config file, or they name an address that is already
@@ -804,11 +831,13 @@ final cost inputs, a board/calendar toggle, and the Inbox import from
804
831
  Pages, skip its config file and write only the content file.
805
832
 
806
833
  Third β€” a request copied from a page's own row on the Pages screen. The owner
807
- added the page there first (who it is for, its name, its web address, a
808
- starting layout, its form), then pasted the row's sentence and finished it.
809
- When the owner gave the page a form of its own, the sentence also names the
810
- one \`*Form.config.ts\` to create, its \`systemName\` and its \`formType\` β€” write
811
- that file too, with exactly those values, and nothing more:
834
+ added the page there first β€” who it is for, and one box describing it, its
835
+ name first; the screen made its web address β€” and pasted the row's sentence.
836
+ When the owner described a form, the sentence names the one \`*Form.config.ts\`
837
+ to create, its \`systemName\` and its \`formType\` β€” write that file too, with
838
+ exactly those values, and nothing more β€” unless their words name a form the
839
+ app already has, which you show instead. Whatever the sentence leaves
840
+ undecided, decide yourself; it says so:
812
841
 
813
842
  > "My app already has a page called Client onboarding at /onboarding. It is
814
843
  > already made and it is already in the menu β€” do not create a page, a web
@@ -824,6 +853,9 @@ that file too, with exactly those values, and nothing more:
824
853
  > Never remove another page's lines from that file.
825
854
  > Make it match the rest of my app: style with the app's own theme styles so
826
855
  > it looks right in light and dark. Do not pick your own colors.
856
+ > Anything I have not decided below β€” the section titles, the words on the
857
+ > buttons, the layout, where the pictures and the form go β€” decide yourself
858
+ > and build it finished; do not stop to ask me.
827
859
  > This page already works as a board and it stays one: it keeps its board
828
860
  > frame and the card editor that is already in it, already styled to match my
829
861
  > app. Design only what fills it, and open the one that is already there with
@@ -888,8 +920,9 @@ calendar picker; the answer is stored as \`YYYY-MM-DD\`), \`select\` (needs
888
920
  or several β€” each uploads as it is picked, and the Inbox entry links to every
889
921
  one; the answer is a string holding the links, one per line; optional
890
922
  \`accept\`, e.g. \`'image/*'\` or \`'.pdf,.doc,.docx'\`), \`schedule\` (a time to
891
- book with the owner's team β€” needs \`members\`, the team member ids the
892
- owner's sentence gives you, and \`look\`, \`'calendar'\` or \`'compact'\`; the
923
+ book with the owner's team β€” needs \`schedules\`, the schedule ids the
924
+ owner's sentence gives you (each a kind of meeting with its own length, so
925
+ never state one), and \`look\`, \`'calendar'\` or \`'compact'\`; the
893
926
  built-in form draws the picker in the visitor's own time zone and the answer
894
927
  is stored as a readable line plus \`<name>Start\`, \`<name>End\`, \`<name>With\`
895
928
  and \`<name>TimeZone\` beside it β€” checklist rule 12). Any other value renders
@@ -1089,9 +1122,9 @@ the package: \`import { db, useAuth } from 'your-ai-workflow-firebase-os'\` and
1089
1122
  | \`user_submissions\` | entries from forms open to ANYONE (Inbox, "From anyone") | every form field under its \`name\`, plus \`formId\`, \`submittedAt\`, \`uid\` (\`'guest'\`) | admins only |
1090
1123
  | \`user_requests\` | entries from forms for SIGNED-IN people (Inbox, "From signed-in users") | the same, plus \`submitterName\`, \`submitterEmail\`, \`submitterAvatar\`, the sender's \`uid\` | admins and the sender |
1091
1124
  | \`user_profiles\` | one document per registered person; the document id is their uid | \`email\`, \`displayName\`, \`role\` (\`'admin'\`, \`'internal'\`, anything else = free) | admins only |
1092
- | \`sys_schedules\` | each team member's bookable hours, set on the Schedule screen | \`name\`, \`enabled\`, \`timeZone\`, \`slotMinutes\`, \`days\`, \`horizonDays\`, \`noticeHours\` | anyone reads; NEVER write it β€” the Schedule screen owns it |
1125
+ | \`sys_schedules\` | the schedules made on the Schedule screen β€” one per kind of meeting a team member offers; several of one person share their availability | \`memberId\`, \`memberName\`, \`name\`, \`description\`, \`paymentId\`, \`enabled\`, \`timeZone\`, \`slotMinutes\`, \`days\`, \`horizonDays\`, \`noticeHours\` | anyone reads; NEVER write it β€” the Schedule screen owns it |
1093
1126
  | \`pub_bookings\` | the times already taken β€” no names, no emails | \`memberId\`, \`start\`, \`end\` | anyone; NEVER touch it β€” the built-in form claims a time, and a hand-written claim is a double booking |
1094
- | \`mem_bookings\` | the team's bookings β€” who booked, with whom, when, what they answered | \`memberId\`, \`memberName\`, \`start\`, \`end\`, \`name\`, \`email\`, \`answers\`, \`formId\`, \`entryId\` | the team β€” and ONLY through \`useBookings()\` from the package; never \`onSnapshot\` on it by hand |
1127
+ | \`mem_bookings\` | the team's bookings β€” who booked, with whom, under which schedule, when, what they answered | \`memberId\`, \`memberName\`, \`scheduleId\`, \`scheduleName\`, \`start\`, \`end\`, \`name\`, \`email\`, \`answers\`, \`formId\`, \`entryId\`, \`paymentId\`, \`paymentSession\` | the team β€” and ONLY through \`useBookings()\` from the package; never \`onSnapshot\` on it by hand |
1095
1128
 
1096
1129
  "Every new entry in the Inbox automatically becomes a lead / ticket / card"
1097
1130
  therefore means: while an ADMIN has the page open, mirror each entry into the
@@ -1192,9 +1225,10 @@ What to know before promising email anywhere:
1192
1225
  \`details\` as \`{ label: value }\`, where they become rows.
1193
1226
 
1194
1227
  - Email only works once the owner has connected it (a Resend key on the
1195
- setup page). Both calls come back with a readable message when it is not
1196
- β€” show nothing or a quiet fallback, never a red error over a page that
1197
- otherwise worked.
1228
+ setup page) and while the Send email switch on the Email screen is on.
1229
+ Every call comes back with a readable message when it is not β€” show
1230
+ nothing or a quiet fallback, never a red error over a page that otherwise
1231
+ worked.
1198
1232
  - \`emailPerson\` reads the record AS THE CALLER β€” it carries the signed-in
1199
1233
  person's token itself, and a signed-in sender's entry always names their
1200
1234
  address, so a form need not ask for one. A visitor who is not signed
@@ -1248,4 +1282,4 @@ in one sentence, and do not go looking for the files.
1248
1282
 
1249
1283
  The home page cannot be removed β€” it is the site's front door. Redesign it
1250
1284
  instead.
1251
- `;exports.aiRules=e;
1285
+ `;export{e as aiRules};