3 Commits
53 changed files with 120 additions and 623 deletions
+3
View File
@@ -19,6 +19,9 @@
/public/sitemap.xml /public/sitemap.xml
/public/logos/core /public/logos/core
/public/storage /public/storage
/public/css/filament
/public/js/filament
/public/fonts/filament
/storage/*.key /storage/*.key
/storage/framework/migrated /storage/framework/migrated
/storage/pail /storage/pail
+32 -11
View File
@@ -5,17 +5,38 @@ set -e
# by app only) — just wait for app's migration to finish, then start the process. # by app only) — just wait for app's migration to finish, then start the process.
mkdir -p storage/app/public storage/framework/cache storage/framework/sessions storage/framework/views storage/logs storage/framework bootstrap/cache mkdir -p storage/app/public storage/framework/cache storage/framework/sessions storage/framework/views storage/logs storage/framework bootstrap/cache
if [ "$APP_ENV" != "production" ]; then # Same reasoning as entrypoint.sh: this container gets replaced on every deploy
echo "[entrypoint] Waiting for migrations to complete..." # (dev and production alike), so this is a fresh boot clearing stale artifacts
timeout=60 # left on disk (cached config, compiled views), not a running process being
while [ ! -f storage/framework/migrated ] && [ "$timeout" -gt 0 ]; do # told to forget in-memory code. queue:work/schedule:work themselves still
sleep 1 # can't pick up a later code change without an actual process restart — this
timeout=$((timeout - 1)) # only fixes what's stale on disk at boot.
done echo "[entrypoint] Clearing cached config/routes/views..."
if [ ! -f storage/framework/migrated ]; then php artisan optimize:clear --quiet
echo "[entrypoint] Timed out waiting for migrations" >&2 echo "[entrypoint] Caches cleared"
exit 1
fi # Universal, in both dev and production — app's entrypoint always writes this
# marker after `migrate --force` completes (single app instance, so there's
# exactly one writer), and queue/scheduler must never start against a database
# schema that migration hasn't finished bringing up to date yet.
echo "[entrypoint] Waiting for migrations to complete..."
timeout=60
while [ ! -f storage/framework/migrated ] && [ "$timeout" -gt 0 ]; do
sleep 1
timeout=$((timeout - 1))
done
if [ ! -f storage/framework/migrated ]; then
echo "[entrypoint] Timed out waiting for migrations" >&2
exit 1
fi
if [ "$APP_ENV" = "production" ]; then
# Same reasoning as entrypoint.sh's own production-only optimize step —
# queue:work/schedule:work read config on every job/tick too, so this
# avoids paying the same uncached-config cost app pays per request.
echo "[entrypoint] Caching config/routes/views for production..."
php artisan optimize --quiet
echo "[entrypoint] Production caches built"
fi fi
exec "$@" exec "$@"
+63 -22
View File
@@ -4,6 +4,12 @@ set -e
# Only the app container runs setup; queue/scheduler use entrypoint-worker.sh instead # Only the app container runs setup; queue/scheduler use entrypoint-worker.sh instead
# and just wait on the migrated marker this script writes below. # and just wait on the migrated marker this script writes below.
if [ "$APP_ENV" != "production" ]; then if [ "$APP_ENV" != "production" ]; then
# Dev-only: the app dir is bind-mounted from a fresh checkout, so there's no
# image-build step that already installed vendor/ or published assets — this
# container has to do it at boot instead. In production the Dockerfile already
# runs composer install and asset publishing at IMAGE BUILD time (see
# Dockerfile's `production` stage), so repeating them here would be wasteful,
# not just redundant-but-safe.
echo "[entrypoint] Installing Composer dependencies..." echo "[entrypoint] Installing Composer dependencies..."
git config --global --add safe.directory /var/www/html 2>/dev/null || true git config --global --add safe.directory /var/www/html 2>/dev/null || true
git config --global --add safe.directory /var/www/boboko-core 2>/dev/null || true git config --global --add safe.directory /var/www/boboko-core 2>/dev/null || true
@@ -21,38 +27,73 @@ mkdir -p storage/app/public storage/framework/cache storage/framework/sessions s
chown -R www-data:www-data storage bootstrap/cache chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache chmod -R 775 storage bootstrap/cache
# Composer packages (dev) may have just changed above, or (production) this is a
# freshly built image — either way, clear any cached config/routes/compiled views
# left over from a previous boot before anything below reads them. Production
# runs a single app instance that gets replaced on every deploy, not a running
# process being told to forget in-memory code — the actual bug this fixes is
# stale artifacts still sitting in bootstrap/cache or storage/framework/views on
# a fresh boot (e.g. after the Lunar 1.5/Filament v4 upgrade, a leftover compiled
# view referenced a class that upgrade removed).
echo "[entrypoint] Clearing cached config/routes/views..."
php artisan optimize:clear --quiet
echo "[entrypoint] Caches cleared"
php artisan storage:link --quiet 2>/dev/null || true php artisan storage:link --quiet 2>/dev/null || true
if [ "$APP_ENV" != "production" ]; then if [ "$APP_ENV" != "production" ]; then
# The app dir is bind-mounted from a fresh checkout, so package assets (which the # Dev-only for the same reason as the composer step above — production's
# Dockerfile publishes at build time in production) need to be generated here # image already has these published at build time.
# instead. Cheap and idempotent, safe to repeat on every boot.
php artisan vendor:publish --tag=core-assets --force --ansi --quiet php artisan vendor:publish --tag=core-assets --force --ansi --quiet
php artisan vendor:publish --tag=public --force --ansi --quiet php artisan vendor:publish --tag=public --force --ansi --quiet
php artisan filament:assets --ansi --quiet php artisan filament:assets --ansi --quiet
fi
echo "[entrypoint] Running migrations..." # Everything below is universal, in both dev and production: application STATE
rm -f storage/framework/migrated # that must be current on every boot, not a build-time concern composer/assets
php artisan migrate --force # are. Safe to run unconditionally on every boot because production runs a
echo "[entrypoint] Touching migrated file" # single app instance — no concurrent replicas that would race each other
touch storage/framework/migrated # running `migrate --force` at the same time.
echo "[entrypoint] Touched migrated file"
echo "[entrypoint] Running migrations..."
rm -f storage/framework/migrated
php artisan migrate --force
echo "[entrypoint] Touching migrated file"
touch storage/framework/migrated
echo "[entrypoint] Touched migrated file"
# boboko/core overrides lunar:install to skip the interactive prompts (migrate # boboko/core overrides lunar:install to skip the interactive prompts (migrate
# confirm, admin creation, GitHub star) and just seed the idempotent store # confirm, admin creation, GitHub star) and just seed the idempotent store
# defaults: countries, channel, language, currency, tax zone, attributes, # defaults: countries, channel, language, currency, tax zone, attributes,
# product type. queue/scheduler wait on the marker above rather than running # product type. queue/scheduler wait on the marker above rather than running
# this themselves, since the country import's check-then-insert isn't safe to # this themselves, since the country import's check-then-insert isn't safe to
# run concurrently. # run concurrently. A fresh production install needs this seeding the same as
echo "[entrypoint] Trying Lunar install" # a fresh dev one does — and re-running it against an already-seeded store is
php artisan lunar:install --quiet || true # a no-op per key (see InstallLunarCommand's idempotent upserts).
echo "[entrypoint] Trying Lunar install"
php artisan lunar:install --quiet || true
# Upserts by primary key (no --refresh), so this stays cheap and idempotent on # Upserts by primary key (no --refresh), so this stays cheap and idempotent on
# every boot rather than flushing and rebuilding the whole index each time. # every boot rather than flushing and rebuilding the whole index each time. Runs
echo "[entrypoint] Syncing search indexes..." # in production too — a deploy that changed an indexer's field list needs this
php artisan lunar:meilisearch:setup # to keep Meilisearch's index settings and documents in sync with the code that
php artisan lunar:search:index --quiet || true # just shipped, same reasoning as optimize:clear above.
echo "[entrypoint] Syncing search indexes..."
php artisan lunar:meilisearch:setup
php artisan lunar:search:index --quiet || true
if [ "$APP_ENV" = "production" ]; then
# The counterpart to optimize:clear above: config/routes/views/events get
# compiled once here, at the end of boot, after everything that could
# change them (migrations, lunar:install, index sync) has already run —
# so production actually gets the request-time performance win caching is
# for, rather than staying permanently uncached. Dev deliberately never
# does this: caching config here would mean .env/config edits stop taking
# effect until the next optimize:clear, which is the opposite of what dev
# needs on every iteration.
echo "[entrypoint] Caching config/routes/views for production..."
php artisan optimize --quiet
echo "[entrypoint] Production caches built"
fi fi
exec "$@" exec "$@"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
.fi-pagination-items,.fi-pagination-overview,.fi-pagination-records-per-page-select:not(.fi-compact){display:none}@supports (container-type:inline-size){.fi-pagination{container-type:inline-size}@container (min-width: 28rem){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@container (min-width: 56rem){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}@supports not (container-type:inline-size){@media(min-width:640px){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@media(min-width:768px){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}.tippy-box[data-theme~=light]{color:#26323d;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;background-color:#fff}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.fi-sortable-ghost{opacity:.3}
@@ -1 +0,0 @@
@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-cyrillic-ext-wght-normal-IYF56FF6.woff2") format("woff2-variations");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-cyrillic-wght-normal-JEOLYBOO.woff2") format("woff2-variations");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-greek-ext-wght-normal-EOVOK2B5.woff2") format("woff2-variations");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-greek-wght-normal-IRE366VL.woff2") format("woff2-variations");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-vietnamese-wght-normal-CE5GGD3W.woff2") format("woff2-variations");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-latin-ext-wght-normal-HA22NDSG.woff2") format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url("./inter-latin-wght-normal-NRMW37G5.woff2") format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
-1
View File
@@ -1 +0,0 @@
(()=>{var o=({livewireId:s})=>({actionNestingIndex:null,shouldOverlayParentActions:!1,closedActionNestingIndexes:[],focusTargetsByNestingIndex:{},boundSyncActionModals:null,boundOnModalClosed:null,init(){this.boundSyncActionModals=e=>{e.detail.id===s&&this.syncActionModals(e.detail.newActionNestingIndex,e.detail.shouldOverlayParentActions??!1)},this.boundOnModalClosed=e=>{let t=this.getActionNestingIndexFromModalId(e.detail.id);t!==null&&((this.shouldOverlayParentActions||t===0)&&this.restorePreviouslyFocusedElement(t-1),this.closedActionNestingIndexes.push(t))},window.addEventListener("sync-action-modals",this.boundSyncActionModals),window.addEventListener("modal-closed",this.boundOnModalClosed)},destroy(){this.boundSyncActionModals&&(window.removeEventListener("sync-action-modals",this.boundSyncActionModals),this.boundSyncActionModals=null),this.boundOnModalClosed&&(window.removeEventListener("modal-closed",this.boundOnModalClosed),this.boundOnModalClosed=null)},syncActionModals(e,t=!1){if(this.actionNestingIndex===e){this.actionNestingIndex!==null&&this.$nextTick(()=>this.openModal());return}let n=this.actionNestingIndex!==null&&e!==null&&e>this.actionNestingIndex,i=this.actionNestingIndex!==null&&e!==null&&e<this.actionNestingIndex,d=this.actionNestingIndex===null&&e!==null;if((n||d)&&this.rememberPreviouslyFocusedElement(),this.actionNestingIndex!==null&&!(t&&n)&&this.closeModal(),this.actionNestingIndex=e,this.actionNestingIndex===null){this.restorePreviouslyFocusedElement(-1),this.closedActionNestingIndexes=[],this.focusTargetsByNestingIndex={},this.shouldOverlayParentActions=!1;return}if(this.shouldOverlayParentActions=t,this.closedActionNestingIndexes=this.closedActionNestingIndexes.filter(l=>l<=this.actionNestingIndex),!this.closedActionNestingIndexes.includes(this.actionNestingIndex)){if(!this.$el.querySelector(`#${this.generateModalId(e)}`)){this.$nextTick(()=>{this.openModal(),i&&this.restorePreviouslyFocusedElement()});return}this.openModal(),i&&this.restorePreviouslyFocusedElement()}},rememberPreviouslyFocusedElement(){let e=this.$focus.focused();if(!e)return;if(this.actionNestingIndex===null){this.focusTargetsByNestingIndex[-1]=e;return}this.$el.querySelector(`#${this.generateModalId(this.actionNestingIndex)}`)?.contains(e)&&(this.focusTargetsByNestingIndex[this.actionNestingIndex]=e)},restorePreviouslyFocusedElement(e=this.actionNestingIndex){let t=this.focusTargetsByNestingIndex[e];if(t){for(let n in this.focusTargetsByNestingIndex)Number(n)>=e&&delete this.focusTargetsByNestingIndex[n];requestAnimationFrame(()=>requestAnimationFrame(()=>this.$nextTick(()=>{t.focus({preventScroll:!0})})))}},generateModalId(e){return`fi-${s}-action-`+e},getActionNestingIndexFromModalId(e){let t=`fi-${s}-action-`;if(!e?.startsWith(t))return null;let n=Number(e.slice(t.length));return Number.isInteger(n)?n:null},openModal(){let e=this.generateModalId(this.actionNestingIndex);document.dispatchEvent(new CustomEvent("open-modal",{bubbles:!0,composed:!0,detail:{id:e}}))},closeModal(){let e=this.generateModalId(this.actionNestingIndex);document.dispatchEvent(new CustomEvent("close-modal-quietly",{bubbles:!0,composed:!0,detail:{id:e}}))}});document.addEventListener("alpine:init",()=>{window.Alpine.data("filamentActionModals",o)});})();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
function c({livewireId:s}){return{areAllCheckboxesChecked:!1,checkboxListOptions:[],search:"",unsubscribeLivewireHook:null,visibleCheckboxListOptions:[],init(){this.checkboxListOptions=Array.from(this.$root.querySelectorAll(".fi-fo-checkbox-list-option")),this.updateVisibleCheckboxListOptions(),this.$nextTick(()=>{this.checkIfAllCheckboxesAreChecked()}),this.unsubscribeLivewireHook=Livewire.hook("commit",({component:e,commit:t,succeed:i,fail:o,respond:h})=>{i(({snapshot:r,effect:l})=>{this.$nextTick(()=>{e.id===s&&(this.checkboxListOptions=Array.from(this.$root.querySelectorAll(".fi-fo-checkbox-list-option")),this.updateVisibleCheckboxListOptions(),this.checkIfAllCheckboxesAreChecked())})})}),this.$watch("search",()=>{this.updateVisibleCheckboxListOptions(),this.checkIfAllCheckboxesAreChecked()})},checkIfAllCheckboxesAreChecked(){this.areAllCheckboxesChecked=this.visibleCheckboxListOptions.length===this.visibleCheckboxListOptions.filter(e=>e.querySelector("input[type=checkbox]:checked, input[type=checkbox]:disabled")).length},toggleAllCheckboxes(){this.checkIfAllCheckboxesAreChecked();let e=!this.areAllCheckboxesChecked;this.visibleCheckboxListOptions.forEach(t=>{let i=t.querySelector("input[type=checkbox]");i.disabled||i.checked!==e&&(i.checked=e,i.dispatchEvent(new Event("change")))}),this.areAllCheckboxesChecked=e},updateVisibleCheckboxListOptions(){this.visibleCheckboxListOptions=this.checkboxListOptions.filter(e=>["",null,void 0].includes(this.search)||e.querySelector(".fi-fo-checkbox-list-option-label")?.innerText.toLowerCase().includes(this.search.toLowerCase())?!0:e.querySelector(".fi-fo-checkbox-list-option-description")?.innerText.toLowerCase().includes(this.search.toLowerCase()))},destroy(){this.unsubscribeLivewireHook?.()}}}export{c as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
function a({state:r}){return{state:r,rows:[],init(){this.updateRows(),this.rows.length<=0?this.rows.push({key:"",value:""}):this.updateState(),this.$watch("state",(e,t)=>{if(!Array.isArray(e))return;let s=i=>i===null?0:Array.isArray(i)?i.length:typeof i!="object"?0:Object.keys(i).length;s(e)===0&&s(t)===0||this.updateRows()})},addRow(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow(e){this.rows.splice(e,1),this.rows.length<=0&&this.addRow(),this.updateState()},reorderRows(e){let t=Alpine.raw(this.rows);this.rows=[];let s=t.splice(e.oldIndex,1)[0];t.splice(e.newIndex,0,s),this.$nextTick(()=>{this.rows=t,this.updateState()})},updateRows(){let t=Alpine.raw(this.state).map(({key:s,value:i})=>({key:s,value:i}));this.rows.forEach(s=>{(s.key===""||s.key===null)&&t.push({key:"",value:s.value})}),this.rows=t},updateState(){let e=[];this.rows.forEach(t=>{t.key===""||t.key===null||e.push({key:t.key,value:t.value})}),JSON.stringify(this.state)!==JSON.stringify(e)&&(this.state=e)}}}export{a as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
function r({state:n,splitKeys:i,tagAddedMessage:a,tagRemovedMessage:s}){return{newTag:"",state:n,liveRegionClearTimeout:null,announce(e){let t=this.$refs.liveRegion;t&&(this.liveRegionClearTimeout!==null&&clearTimeout(this.liveRegionClearTimeout),t.textContent=e,this.liveRegionClearTimeout=setTimeout(()=>{t.textContent="",this.liveRegionClearTimeout=null},3e3))},createTag(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.announce(a?.replace(":tag",()=>this.newTag)),this.newTag=""}},deleteTag(e){this.state=this.state.filter(t=>t!==e),this.announce(s?.replace(":tag",()=>e))},reorderTags(e){let t=this.state.splice(e.oldIndex,1)[0];this.state.splice(e.newIndex,0,t),this.state=[...this.state]},input:{"x-on:blur":"createTag()","x-model":"newTag","x-on:keydown"(e){["Enter",...i].includes(e.key)&&(e.preventDefault(),e.stopPropagation(),this.createTag())},"x-on:paste"(){this.$nextTick(()=>{if(i.length===0){this.createTag();return}let e=i.map(t=>t.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")).join("|");this.newTag.split(new RegExp(e,"g")).forEach(t=>{this.newTag=t,this.createTag()})})}}}}export{r as default};
@@ -1 +0,0 @@
function n({initialHeight:e,shouldAutosize:i,state:h}){return{state:h,wrapperEl:null,init(){this.wrapperEl=this.$el.parentNode,this.setInitialHeight(),i?this.$watch("state",()=>{this.resize()}):this.setUpResizeObserver()},setInitialHeight(){this.$el.scrollHeight<=0||(this.wrapperEl.style.height=e+"rem")},resize(){if(this.$el.scrollHeight<=0)return;let t=this.$el.style.height;this.$el.style.height="0px";let r=this.$el.scrollHeight;this.$el.style.height=t;let l=parseFloat(e)*parseFloat(getComputedStyle(document.documentElement).fontSize),s=Math.max(r,l)+"px";this.wrapperEl.style.height!==s&&(this.wrapperEl.style.height=s)},setUpResizeObserver(){new ResizeObserver(()=>{this.wrapperEl.style.height=this.$el.style.height}).observe(this.$el)}}}export{n as default};
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
var i=()=>({isSticky:!1,width:0,resizeObserver:null,boundUpdateWidth:null,init(){let e=this.$el.parentElement;e&&(this.updateWidth(),this.resizeObserver=new ResizeObserver(()=>this.updateWidth()),this.resizeObserver.observe(e),this.boundUpdateWidth=this.updateWidth.bind(this),window.addEventListener("resize",this.boundUpdateWidth))},enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1},updateWidth(){let e=this.$el.parentElement;if(!e)return;let t=getComputedStyle(this.$root.querySelector(".fi-ac"));this.width=e.offsetWidth+parseInt(t.marginInlineStart,10)*-1+parseInt(t.marginInlineEnd,10)*-1},destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.boundUpdateWidth&&(window.removeEventListener("resize",this.boundUpdateWidth),this.boundUpdateWidth=null)}});export{i as default};
@@ -1 +0,0 @@
function x({activeTab:p,isScrollable:m,isTabPersisted:T,isTabPersistedInQueryString:w,livewireId:g,schemaKey:D,tab:W,tabQueryStringKey:r}){return{boundResizeHandler:null,boundResetHandler:null,isScrollable:m,resizeDebounceTimer:null,tab:W,unsubscribeLivewireHook:null,withinDropdownIndex:null,withinDropdownMounted:!1,init(){let t=this.getTabs(),e=new URLSearchParams(window.location.search);w&&e.has(r)&&t.includes(e.get(r))&&(this.tab=e.get(r)),(!this.tab||!t.includes(this.tab))&&(this.tab=t[p-1]),this.$watch("tab",()=>{this.updateQueryString(),this.autofocusFields()}),this.autofocusFields(!0),this.unsubscribeLivewireHook=Livewire.hook("commit",({component:i,commit:d,succeed:c,fail:h,respond:u})=>{c(({snapshot:b,effect:n})=>{this.$nextTick(()=>{if(i.id!==g)return;let o=this.getTabs();o.includes(this.tab)||(this.tab=o[p-1]??this.tab)})})}),this.boundResetHandler=i=>{i.detail.livewireId!==g||i.detail.schemaKey!==D||T||w||this.$nextTick(()=>{this.tab=this.getTabs()[p-1]??this.tab})},window.addEventListener("reset-schema-component-state",this.boundResetHandler),m||(this.boundResizeHandler=this.debouncedUpdateTabsWithinDropdown.bind(this),window.addEventListener("resize",this.boundResizeHandler),this.updateTabsWithinDropdown())},calculateAvailableWidth(t){let e=window.getComputedStyle(t);return Math.floor(t.clientWidth)-Math.ceil(parseFloat(e.paddingLeft))*2},calculateContainerGap(t){let e=window.getComputedStyle(t);return Math.ceil(parseFloat(e.columnGap))},calculateDropdownIconWidth(t){let e=t.querySelector(".fi-icon");return Math.ceil(e.clientWidth)},calculateTabItemGap(t){let e=window.getComputedStyle(t);return Math.ceil(parseFloat(e.columnGap)||8)},calculateTabItemPadding(t){let e=window.getComputedStyle(t);return Math.ceil(parseFloat(e.paddingLeft))+Math.ceil(parseFloat(e.paddingRight))},findOverflowIndex(t,e,i,d,c,h){let u=t.map(n=>Math.ceil(n.clientWidth)),b=t.map(n=>{let o=n.querySelector(".fi-tabs-item-label"),s=n.querySelector(".fi-badge"),a=Math.ceil(o.clientWidth),l=s?Math.ceil(s.clientWidth):0;return{label:a,badge:l,total:a+(l>0?d+l:0)}});for(let n=0;n<t.length;n++){let o=u.slice(0,n+1).reduce((f,I)=>f+I,0),s=n*i,a=b.slice(n+1),l=a.length>0,v=l?Math.max(...a.map(f=>f.total)):0,y=l?c+v+d+h+i:0;if(o+s+y>e)return n}return-1},get isDropdownButtonVisible(){return this.withinDropdownMounted?this.withinDropdownIndex===null?!1:this.getTabs().findIndex(e=>e===this.tab)<this.withinDropdownIndex:!0},getTabs(){return this.$refs.tabsData?JSON.parse(this.$refs.tabsData.value):[]},updateQueryString(){if(!w)return;let t=new URL(window.location.href);t.searchParams.set(r,this.tab),history.replaceState(null,document.title,t.toString())},autofocusFields(t=!1){this.$nextTick(()=>{if(t&&document.activeElement&&document.activeElement!==document.body&&this.$el.compareDocumentPosition(document.activeElement)&Node.DOCUMENT_POSITION_PRECEDING)return;let e=this.$el.querySelectorAll(".fi-sc-tabs-tab.fi-active [autofocus]");for(let i of e)if(i.focus(),document.activeElement===i)break})},debouncedUpdateTabsWithinDropdown(){clearTimeout(this.resizeDebounceTimer),this.resizeDebounceTimer=setTimeout(()=>this.updateTabsWithinDropdown(),150)},async updateTabsWithinDropdown(){this.withinDropdownIndex=null,this.withinDropdownMounted=!1,await this.$nextTick();let t=this.$el.querySelector(".fi-tabs"),e=t.querySelector(".fi-tabs-item:last-child"),i=Array.from(t.children).slice(0,-1),d=i.map(s=>s.style.display);i.forEach(s=>s.style.display=""),t.offsetHeight;let c=this.calculateAvailableWidth(t),h=this.calculateContainerGap(t),u=this.calculateDropdownIconWidth(e),b=this.calculateTabItemGap(i[0]),n=this.calculateTabItemPadding(i[0]),o=this.findOverflowIndex(i,c,h,b,n,u);i.forEach((s,a)=>s.style.display=d[a]),o!==-1&&(this.withinDropdownIndex=o),this.withinDropdownMounted=!0},destroy(){this.unsubscribeLivewireHook?.(),this.boundResetHandler&&window.removeEventListener("reset-schema-component-state",this.boundResetHandler),this.boundResizeHandler&&window.removeEventListener("resize",this.boundResizeHandler),clearTimeout(this.resizeDebounceTimer)}}}export{x as default};
@@ -1 +0,0 @@
function l({isSkippable:i,isStepPersistedInQueryString:n,key:o,livewireId:h,schemaKey:p,startStep:r,stepQueryStringKey:d}){return{boundResetHandler:null,step:null,init(){this.step=this.getSteps().at(r-1),this.$watch("step",()=>{this.updateQueryString(),this.autofocusFields()}),this.autofocusFields(!0),this.boundResetHandler=t=>{t.detail.livewireId!==h||t.detail.schemaKey!==p||n||this.$nextTick(()=>{this.step=this.getSteps().at(r-1)??this.step})},window.addEventListener("reset-schema-component-state",this.boundResetHandler)},async requestNextStep(){await this.$wire.callSchemaComponentMethod(o,"nextStep",{currentStepIndex:this.getStepIndex(this.step)})},goToNextStep(){let t=this.getStepIndex(this.step)+1;t>=this.getSteps().length||(this.step=this.getSteps()[t],this.scroll())},goToPreviousStep(){let t=this.getStepIndex(this.step)-1;t<0||(this.step=this.getSteps()[t],this.scroll())},goToStep(t){let e=this.getStepIndex(t);e<=-1||!i&&e>this.getStepIndex(this.step)||(this.step=t,this.scroll())},scroll(){this.$nextTick(()=>{this.$refs.header?.children[this.getStepIndex(this.step)].scrollIntoView({behavior:"smooth",block:"start"})})},autofocusFields(t=!1){this.$nextTick(()=>{if(t&&document.activeElement&&document.activeElement!==document.body&&this.$el.compareDocumentPosition(document.activeElement)&Node.DOCUMENT_POSITION_PRECEDING)return;let e=this.$refs[`step-${this.step}`]?.querySelectorAll("[autofocus]")??[];for(let s of e)if(s.focus(),document.activeElement===s)break})},getStepIndex(t){let e=this.getSteps().findIndex(s=>s===t);return e===-1?0:e},getSteps(){return JSON.parse(this.$refs.stepsData.value)},isFirstStep(){return this.getStepIndex(this.step)<=0},isLastStep(){return this.getStepIndex(this.step)+1>=this.getSteps().length},isStepAccessible(t){return i||this.getStepIndex(this.step)>this.getStepIndex(t)},updateQueryString(){if(!n)return;let t=new URL(window.location.href);t.searchParams.set(d,this.step),history.replaceState(null,document.title,t.toString())},destroy(){this.boundResetHandler&&window.removeEventListener("reset-schema-component-state",this.boundResetHandler)}}}export{l as default};
-1
View File
@@ -1 +0,0 @@
(()=>{var d=()=>({isSticky:!1,width:0,resizeObserver:null,boundUpdateWidth:null,init(){let i=this.$el.parentElement;i&&(this.updateWidth(),this.resizeObserver=new ResizeObserver(()=>this.updateWidth()),this.resizeObserver.observe(i),this.boundUpdateWidth=this.updateWidth.bind(this),window.addEventListener("resize",this.boundUpdateWidth))},enableSticky(){this.isSticky=this.$el.getBoundingClientRect().top>0},disableSticky(){this.isSticky=!1},updateWidth(){let i=this.$el.parentElement;if(!i)return;let e=getComputedStyle(this.$root.querySelector(".fi-ac"));this.width=i.offsetWidth+parseInt(e.marginInlineStart,10)*-1+parseInt(e.marginInlineEnd,10)*-1},destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.boundUpdateWidth&&(window.removeEventListener("resize",this.boundUpdateWidth),this.boundUpdateWidth=null)}});var u=function(i,e,n){let t=i;if(e.startsWith("/")&&(n=!0,e=e.slice(1)),n)return e;for(;e.startsWith("../");)t=t.includes(".")?t.slice(0,t.lastIndexOf(".")):null,e=e.slice(3);return["",null,void 0].includes(t)?e:["",null,void 0].includes(e)?t:`${t}.${e}`},h=i=>{let e=Alpine.findClosest(i,n=>n.__livewire);if(!e)throw"Could not find Livewire component in DOM tree.";return e.__livewire};document.addEventListener("alpine:init",()=>{window.Alpine.data("filamentSchema",({livewireId:i,schemaKey:e})=>({handleFormValidationError(n){n.detail.livewireId===i&&this.$nextTick(()=>{let t=this.$el.querySelector("[data-validation-error]");if(!t)return;let r=t;for(;r;)r.dispatchEvent(new CustomEvent("expand")),r=r.parentNode;setTimeout(()=>t.closest("[data-field-wrapper]").scrollIntoView({behavior:"smooth",block:"start",inline:"start"}),200)})},handleClientSideStateReset(n){n.detail.livewireId!==i||n.detail.schemaKey!==e||this.$nextTick(()=>{let t=this.$el.querySelectorAll("[autofocus]");for(let r of t)if(r.offsetParent!==null&&(r.focus(),document.activeElement===r))break})},isStateChanged(n,t){if(n===void 0)return!1;try{return JSON.stringify(n)!==JSON.stringify(t)}catch{return n!==t}}})),window.Alpine.data("filamentSchemaComponent",({path:i,containerPath:e,$wire:n})=>({$statePath:i,$get:(t,r)=>n.$get(u(e,t,r)),$set:(t,r,a,o=!1)=>n.$set(u(e,t,a),r,o),get $state(){return n.$get(i)}})),window.Alpine.data("filamentActionsSchemaComponent",d),Livewire.hook("commit",({component:i,commit:e,respond:n,succeed:t,fail:r})=>{t(({snapshot:a,effects:o})=>{o.dispatches?.forEach(s=>{if(!s.params?.awaitSchemaComponent)return;let l=Array.from(i.el.querySelectorAll(`[wire\\:partial="schema-component::${s.params.awaitSchemaComponent}"]`)).filter(c=>h(c)===i);if(l.length!==1){if(l.length>1)throw`Multiple schema components found with key [${s.params.awaitSchemaComponent}].`;window.addEventListener(`schema-component-${i.id}-${s.params.awaitSchemaComponent}-loaded`,()=>{window.dispatchEvent(new CustomEvent(s.name,{detail:s.params}))},{once:!0})}})})})});})();
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
function o({name:r,recordKey:s,state:n}){return{error:void 0,isLoading:!1,state:n,unsubscribeLivewireHook:null,init(){this.unsubscribeLivewireHook=Livewire.hook("commit",({component:e,commit:i,succeed:a,fail:u,respond:h})=>{a(({snapshot:d,effect:f})=>{this.$nextTick(()=>{if(this.isLoading||e.id!==this.$root.closest("[wire\\:id]")?.attributes["wire:id"].value)return;let t=this.getServerState();t===void 0||Alpine.raw(this.state)===t||(this.state=t)})})}),this.$watch("state",async()=>{let e=this.getServerState();if(e===void 0||Alpine.raw(this.state)===e)return;this.isLoading=!0;let i=await this.$wire.updateTableColumnState(r,s,this.state);this.error=i?.error??void 0,!this.error&&this.$refs.serverState&&(this.$refs.serverState.value=this.state?"1":"0"),this.isLoading=!1})},getServerState(){if(this.$refs.serverState)return[1,"1"].includes(this.$refs.serverState.value)},destroy(){this.unsubscribeLivewireHook?.()}}}export{o as default};
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
function o({name:i,recordKey:s,state:n}){return{error:void 0,isLoading:!1,state:n,unsubscribeLivewireHook:null,init(){this.unsubscribeLivewireHook=Livewire.hook("commit",({component:e,commit:r,succeed:a,fail:u,respond:d})=>{a(({snapshot:h,effect:l})=>{this.$nextTick(()=>{if(this.isLoading||e.id!==this.$root.closest("[wire\\:id]")?.attributes["wire:id"].value)return;let t=this.getServerState();t===void 0||this.getNormalizedState()===t||(this.state=t)})})}),this.$watch("state",async()=>{let e=this.getServerState();if(e===void 0||this.getNormalizedState()===e)return;this.isLoading=!0;let r=await this.$wire.updateTableColumnState(i,s,this.state);this.error=r?.error??void 0,!this.error&&this.$refs.serverState&&(this.$refs.serverState.value=this.getNormalizedState()),this.isLoading=!1})},getServerState(){if(this.$refs.serverState)return[null,void 0].includes(this.$refs.serverState.value)?"":this.$refs.serverState.value.replaceAll('\\"','"')},getNormalizedState(){let e=Alpine.raw(this.state);return[null,void 0].includes(e)?"":e},destroy(){this.unsubscribeLivewireHook?.()}}}export{o as default};
@@ -1 +0,0 @@
function o({name:r,recordKey:s,state:n}){return{error:void 0,isLoading:!1,state:n,unsubscribeLivewireHook:null,init(){this.unsubscribeLivewireHook=Livewire.hook("commit",({component:e,commit:i,succeed:a,fail:u,respond:h})=>{a(({snapshot:d,effect:f})=>{this.$nextTick(()=>{if(this.isLoading||e.id!==this.$root.closest("[wire\\:id]")?.attributes["wire:id"].value)return;let t=this.getServerState();t===void 0||Alpine.raw(this.state)===t||(this.state=t)})})}),this.$watch("state",async()=>{let e=this.getServerState();if(e===void 0||Alpine.raw(this.state)===e)return;this.isLoading=!0;let i=await this.$wire.updateTableColumnState(r,s,this.state);this.error=i?.error??void 0,!this.error&&this.$refs.serverState&&(this.$refs.serverState.value=this.state?"1":"0"),this.isLoading=!1})},getServerState(){if(this.$refs.serverState)return[1,"1"].includes(this.$refs.serverState.value)},destroy(){this.unsubscribeLivewireHook?.()}}}export{o as default};
@@ -1 +0,0 @@
function d(){return{checkboxClickController:null,collapsedGroups:[],isLoading:!1,selectedRecords:[],shouldCheckUniqueSelection:!0,lastCheckedRecord:null,livewireId:null,init:function(){this.livewireId=this.$root.closest("[wire\\:id]").attributes["wire:id"].value,this.$wire.$on("deselectAllTableRecords",()=>this.deselectAllRecords()),this.$watch("selectedRecords",()=>{if(!this.shouldCheckUniqueSelection){this.shouldCheckUniqueSelection=!0;return}this.selectedRecords=[...new Set(this.selectedRecords)],this.shouldCheckUniqueSelection=!1}),this.$nextTick(()=>this.watchForCheckboxClicks()),Livewire.hook("element.init",({component:e})=>{e.id===this.livewireId&&this.watchForCheckboxClicks()})},mountAction:function(e,t=null){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableAction(e,t)},mountBulkAction:function(e){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableBulkAction(e)},toggleSelectRecordsOnPage:function(){let e=this.getRecordsOnPage();if(this.areRecordsSelected(e)){this.deselectRecords(e);return}this.selectRecords(e)},toggleSelectRecordsInGroup:async function(e){this.isLoading=!0;let t=await this.$wire.getGroupedSelectableTableRecordKeys(e);this.areRecordsSelected(this.getRecordsInGroupOnPage(e))?this.deselectRecords(t):this.selectRecords(t),this.isLoading=!1},getRecordsInGroupOnPage:function(e){let t=[];for(let s of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])s.dataset.group===e&&t.push(s.value);return t},getRecordsOnPage:function(){let e=[];for(let t of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])e.push(t.value);return e},selectRecords:function(e){for(let t of e)this.isRecordSelected(t)||this.selectedRecords.push(t)},deselectRecords:function(e){for(let t of e){let s=this.selectedRecords.indexOf(t);s!==-1&&this.selectedRecords.splice(s,1)}},selectAllRecords:async function(){this.isLoading=!0,this.selectedRecords=await this.$wire.getAllSelectableTableRecordKeys(),this.isLoading=!1},deselectAllRecords:function(){this.selectedRecords=[]},isRecordSelected:function(e){return this.selectedRecords.includes(e)},areRecordsSelected:function(e){return e.every(t=>this.isRecordSelected(t))},toggleCollapseGroup:function(e){if(this.isGroupCollapsed(e)){this.collapsedGroups.splice(this.collapsedGroups.indexOf(e),1);return}this.collapsedGroups.push(e)},isGroupCollapsed:function(e){return this.collapsedGroups.includes(e)},resetCollapsedGroups:function(){this.collapsedGroups=[]},watchForCheckboxClicks:function(){this.checkboxClickController&&this.checkboxClickController.abort(),this.checkboxClickController=new AbortController;let{signal:e}=this.checkboxClickController;this.$root?.addEventListener("click",t=>t.target?.matches(".fi-ta-record-checkbox")&&this.handleCheckboxClick(t,t.target),{signal:e})},handleCheckboxClick:function(e,t){if(!this.lastChecked){this.lastChecked=t;return}if(e.shiftKey){let s=Array.from(this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[]);if(!s.includes(this.lastChecked)){this.lastChecked=t;return}let l=s.indexOf(this.lastChecked),r=s.indexOf(t),o=[l,r].sort((c,n)=>c-n),i=[];for(let c=o[0];c<=o[1];c++)s[c].checked=t.checked,i.push(s[c].value);t.checked?this.selectRecords(i):this.deselectRecords(i)}this.lastChecked=t}}}export{d as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -4,7 +4,7 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
src: url("/fonts/manrope/manrope-v20-greek_latin-300.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-300.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/* manrope-regular - greek_latin */ /* manrope-regular - greek_latin */
@@ -13,7 +13,7 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: url("/fonts/manrope/manrope-v20-greek_latin-regular.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-regular.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/* manrope-500 - greek_latin */ /* manrope-500 - greek_latin */
@@ -22,7 +22,7 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: url("/fonts/manrope/manrope-v20-greek_latin-500.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-500.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/* manrope-600 - greek_latin */ /* manrope-600 - greek_latin */
@@ -31,7 +31,7 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 600; font-weight: 600;
src: url("/fonts/manrope/manrope-v20-greek_latin-600.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-600.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/* manrope-700 - greek_latin */ /* manrope-700 - greek_latin */
@@ -40,7 +40,7 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: url("/fonts/manrope/manrope-v20-greek_latin-700.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-700.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
/* manrope-800 - greek_latin */ /* manrope-800 - greek_latin */
@@ -49,6 +49,6 @@ @font-face {
font-family: "Manrope"; font-family: "Manrope";
font-style: normal; font-style: normal;
font-weight: 800; font-weight: 800;
src: url("/fonts/manrope/manrope-v20-greek_latin-800.woff2") src: url("../fonts/manrope/manrope-v20-greek_latin-800.woff2")
format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
} }
+4 -4
View File
@@ -31,10 +31,10 @@
doesn't reflow the header and headings on load — which otherwise doesn't reflow the header and headings on load — which otherwise
throws off scroll restoration on refresh. Same URLs as the @font-face throws off scroll restoration on refresh. Same URLs as the @font-face
rules in fonts.css, so each is fetched once. --}} rules in fonts.css, so each is fetched once. --}}
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/manrope/manrope-v20-greek_latin-regular.woff2"> <link rel="preload" as="font" type="font/woff2" crossorigin href="{{ \Illuminate\Support\Facades\Vite::asset('resources/fonts/manrope/manrope-v20-greek_latin-regular.woff2') }}">
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/manrope/manrope-v20-greek_latin-500.woff2"> <link rel="preload" as="font" type="font/woff2" crossorigin href="{{ \Illuminate\Support\Facades\Vite::asset('resources/fonts/manrope/manrope-v20-greek_latin-500.woff2') }}">
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/manrope/manrope-v20-greek_latin-700.woff2"> <link rel="preload" as="font" type="font/woff2" crossorigin href="{{ \Illuminate\Support\Facades\Vite::asset('resources/fonts/manrope/manrope-v20-greek_latin-700.woff2') }}">
<link rel="preload" as="font" type="font/woff2" crossorigin href="/fonts/manrope/manrope-v20-greek_latin-800.woff2"> <link rel="preload" as="font" type="font/woff2" crossorigin href="{{ \Illuminate\Support\Facades\Vite::asset('resources/fonts/manrope/manrope-v20-greek_latin-800.woff2') }}">
@vite(['resources/css/app.css', 'resources/js/app.js']) @vite(['resources/css/app.css', 'resources/js/app.js'])
+12 -10
View File
@@ -219,16 +219,18 @@ class="absolute bottom-6 right-8 text-white text-sm"
</x-slot> </x-slot>
</x-ui.tabs> </x-ui.tabs>
<x-product-grid @if(!empty($product['recommendations']))
class="mt-20" <x-product-grid
title="Σχετικά προϊόντα" class="mt-20"
:products="[ title="Σχετικά προϊόντα"
['name' => 'Camper', 'price' => '30', 'image' => null, 'href' => '#'], :products="collect($product['recommendations'])->map(fn (array $recommendation) => [
['name' => 'Ponderer IPA','price' => '25', 'image' => null, 'href' => '#'], 'name' => $recommendation['name'],
['name' => 'Squish Red', 'price' => '35', 'image' => null, 'href' => '#'], 'price' => $recommendation['price'],
['name' => 'Red Light', 'price' => '25', 'image' => null, 'href' => '#'], 'image' => $recommendation['image'],
]" 'href' => route('product.show', ['id' => $recommendation['id']]),
/> ])->all()"
/>
@endif
</div> </div>