🆙 Add cms i using 🆙

This commit is contained in:
Remco
2025-11-25 22:42:56 +01:00
parent 94704e0925
commit d44196149e
35591 changed files with 3601123 additions and 0 deletions
@@ -0,0 +1,29 @@
.fi-sc-actions {
@apply flex h-full flex-col gap-2;
& .fi-sc-actions-label-ctn {
@apply flex items-center gap-x-3;
& .fi-sc-actions-label {
@apply text-sm leading-6 font-medium text-gray-950 dark:text-white;
}
}
&.fi-sticky {
& .fi-ac {
@apply fixed bottom-0 -mx-4 w-full transform bg-white p-4 shadow-lg ring-1 ring-gray-950/5 transition md:bottom-4 md:rounded-xl dark:bg-gray-900 dark:ring-white/10;
}
}
&.fi-vertical-align-start {
@apply justify-start;
}
&.fi-vertical-align-center {
@apply justify-center;
}
&.fi-vertical-align-end {
@apply justify-end;
}
}
@@ -0,0 +1,87 @@
.fi-sc-flex {
@apply flex gap-6;
&.fi-dense {
@apply gap-3;
}
& > .fi-hidden {
@apply hidden;
}
& > .fi-growable {
@apply w-full flex-1;
}
&.fi-from-default {
@apply items-start;
&.fi-vertical-align-center {
@apply items-center;
}
&.fi-vertical-align-end {
@apply items-end;
}
}
&.fi-from-sm {
@apply flex-col sm:flex-row sm:items-start;
&.fi-vertical-align-center {
@apply sm:items-center;
}
&.fi-vertical-align-end {
@apply sm:items-end;
}
}
&.fi-from-md {
@apply flex-col md:flex-row md:items-start;
&.fi-vertical-align-center {
@apply md:items-center;
}
&.fi-vertical-align-end {
@apply md:items-end;
}
}
&.fi-from-lg {
@apply flex-col lg:flex-row lg:items-start;
&.fi-vertical-align-center {
@apply lg:items-center;
}
&.fi-vertical-align-end {
@apply lg:items-end;
}
}
&.fi-from-xl {
@apply flex-col xl:flex-row xl:items-start;
&.fi-vertical-align-center {
@apply xl:items-center;
}
&.fi-vertical-align-end {
@apply xl:items-end;
}
}
&.fi-from-2xl {
@apply flex-col 2xl:flex-row 2xl:items-start;
&.fi-vertical-align-center {
@apply 2xl:items-center;
}
&.fi-vertical-align-end {
@apply 2xl:items-end;
}
}
}
@@ -0,0 +1,7 @@
.fi-sc-form {
@apply flex flex-col gap-6;
&.fi-dense {
@apply gap-3;
}
}
@@ -0,0 +1,333 @@
.fi-sc-fused-group {
& > .fi-sc {
@apply focus-within:ring-primary-600 dark:focus-within:ring-primary-500 shadow-sm ring-1 ring-gray-950/10 focus-within:ring-2 dark:ring-white/20;
}
& .fi-sc {
@apply divide-y divide-gray-950/10 rounded-lg dark:divide-white/20;
& .fi-sc-component {
@apply min-h-full;
& .fi-fo-field {
@apply min-h-full;
}
& .fi-input {
@apply min-h-full;
}
}
& > :first-child .fi-input-wrp {
@apply rounded-t-lg;
}
& > :last-child .fi-input-wrp {
@apply rounded-b-lg;
}
&.fi-grid-cols {
@apply divide-x divide-y-0;
& > :first-child .fi-input-wrp {
@apply rounded-se-none rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply rounded-se-lg rounded-es-none;
}
}
&.sm\:fi-grid-cols {
@apply sm:divide-x sm:divide-y-0;
& > :first-child .fi-input-wrp {
@apply sm:rounded-se-none sm:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply sm:rounded-se-lg sm:rounded-es-none;
}
}
&.md\:fi-grid-cols {
@apply md:divide-x md:divide-y-0;
& > :first-child .fi-input-wrp {
@apply md:rounded-se-none md:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply md:rounded-se-lg md:rounded-es-none;
}
}
&.lg\:fi-grid-cols {
@apply lg:divide-x lg:divide-y-0;
& > :first-child .fi-input-wrp {
@apply lg:rounded-se-none lg:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply lg:rounded-se-lg lg:rounded-es-none;
}
}
&.xl\:fi-grid-cols {
@apply xl:divide-x xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply xl:rounded-se-none xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply xl:rounded-se-lg xl:rounded-es-none;
}
}
&.\32xl\:fi-grid-cols {
@apply 2xl:divide-x 2xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply 2xl:rounded-se-none 2xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply 2xl:rounded-se-lg 2xl:rounded-es-none;
}
}
@supports (container-type: inline-size) {
&.\@3xs\:fi-grid-cols {
@apply @3xs:divide-x @3xs:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @3xs:rounded-se-none @3xs:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @3xs:rounded-se-lg @3xs:rounded-es-none;
}
}
&.\@2xs\:fi-grid-cols {
@apply @2xs:divide-x @2xs:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @2xs:rounded-se-none @2xs:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @2xs:rounded-se-lg @2xs:rounded-es-none;
}
}
&.\@xs\:fi-grid-cols {
@apply @xs:divide-x @xs:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @xs:rounded-se-none @xs:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @xs:rounded-se-lg @xs:rounded-es-none;
}
}
&.\@sm\:fi-grid-cols {
@apply @sm:divide-x @sm:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @sm:rounded-se-none @sm:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @sm:rounded-se-lg @sm:rounded-es-none;
}
}
&.\@md\:fi-grid-cols {
@apply @md:divide-x @md:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @md:rounded-se-none @md:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @md:rounded-se-lg @md:rounded-es-none;
}
}
&.\@lg\:fi-grid-cols {
@apply @lg:divide-x @lg:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @lg:rounded-se-none @lg:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @lg:rounded-se-lg @lg:rounded-es-none;
}
}
&.\@xl\:fi-grid-cols {
@apply @xl:divide-x @xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @xl:rounded-se-none @xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @xl:rounded-se-lg @xl:rounded-es-none;
}
}
&.\@2xl\:fi-grid-cols {
@apply @2xl:divide-x @2xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @2xl:rounded-se-none @2xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @2xl:rounded-se-lg @2xl:rounded-es-none;
}
}
&.\@3xl\:fi-grid-cols {
@apply @3xl:divide-x @3xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @3xl:rounded-se-none @3xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @3xl:rounded-se-lg @3xl:rounded-es-none;
}
}
&.\@4xl\:fi-grid-cols {
@apply @4xl:divide-x @4xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @4xl:rounded-se-none @4xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @4xl:rounded-se-lg @4xl:rounded-es-none;
}
}
&.\@5xl\:fi-grid-cols {
@apply @5xl:divide-x @5xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @5xl:rounded-se-none @5xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @5xl:rounded-se-lg @5xl:rounded-es-none;
}
}
&.\@6xl\:fi-grid-cols {
@apply @6xl:divide-x @6xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @6xl:rounded-se-none @6xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @6xl:rounded-se-lg @6xl:rounded-es-none;
}
}
&.\@7xl\:fi-grid-cols {
@apply @7xl:divide-x @7xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply @7xl:rounded-se-none @7xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply @7xl:rounded-se-lg @7xl:rounded-es-none;
}
}
}
@supports not (container-type: inline-size) {
&.\!\@sm\:fi-grid-cols {
@apply sm:divide-x sm:divide-y-0;
& > :first-child .fi-input-wrp {
@apply sm:rounded-se-none sm:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply sm:rounded-se-lg sm:rounded-es-none;
}
}
&.\!\@md\:fi-grid-cols {
@apply md:divide-x md:divide-y-0;
& > :first-child .fi-input-wrp {
@apply md:rounded-se-none md:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply md:rounded-se-lg md:rounded-es-none;
}
}
&.\!\@lg\:fi-grid-cols {
@apply lg:divide-x lg:divide-y-0;
& > :first-child .fi-input-wrp {
@apply lg:rounded-se-none lg:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply lg:rounded-se-lg lg:rounded-es-none;
}
}
&.\!\@xl\:fi-grid-cols {
@apply xl:divide-x xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply xl:rounded-se-none xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply xl:rounded-se-lg xl:rounded-es-none;
}
}
&.\!\@2xl\:fi-grid-cols {
@apply 2xl:divide-x 2xl:divide-y-0;
& > :first-child .fi-input-wrp {
@apply 2xl:rounded-se-none 2xl:rounded-es-lg;
}
& > :last-child .fi-input-wrp {
@apply 2xl:rounded-se-lg 2xl:rounded-es-none;
}
}
}
}
& .fi-input-wrp {
@apply rounded-none shadow-none ring-0;
&:not(.fi-disabled):not(:has(.fi-ac-action:focus)) {
@apply focus-within:ring-0;
&.fi-invalid {
@apply focus-within:ring-0;
}
}
}
}
@@ -0,0 +1,7 @@
.fi-sc-icon {
@apply text-gray-400 dark:text-gray-500;
&.fi-color {
@apply text-color-500 dark:text-color-400;
}
}
@@ -0,0 +1,12 @@
.fi-sc-image {
@apply rounded-lg border border-gray-300 dark:border-transparent;
&.fi-align-center {
@apply mx-auto;
}
&.fi-align-end,
&.fi-align-right {
@apply ms-auto;
}
}
@@ -0,0 +1,11 @@
.fi-sc-section {
@apply flex flex-col gap-2;
& .fi-sc-section-label-ctn {
@apply flex items-center gap-x-3;
& .fi-sc-section-label {
@apply text-sm leading-6 font-medium text-gray-950 dark:text-white;
}
}
}
@@ -0,0 +1,35 @@
.fi-sc-tabs {
@apply flex flex-col;
& .fi-sc-tabs-tab {
@apply outline-hidden;
&.fi-active {
@apply mt-6;
}
&:not(.fi-active) {
@apply invisible absolute h-0 overflow-hidden p-0;
}
}
&.fi-contained {
@apply rounded-xl bg-white shadow-xs ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10;
& .fi-sc-tabs-tab {
&.fi-active {
@apply mt-0 p-6;
}
}
}
&.fi-vertical {
@apply flex-row;
& .fi-sc-tabs-tab {
&.fi-active {
@apply ms-6 mt-0 flex-1;
}
}
}
}
@@ -0,0 +1,77 @@
.fi-sc-text {
&.fi-copyable {
@apply cursor-pointer;
}
&.fi-font-sans {
@apply font-sans;
}
&.fi-font-serif {
@apply font-serif;
}
&.fi-font-mono {
@apply font-mono;
}
&:not(.fi-badge) {
@apply inline-block text-sm break-words text-gray-600 dark:text-gray-400;
&.fi-font-thin {
@apply font-thin;
}
&.fi-font-extralight {
@apply font-extralight;
}
&.fi-font-light {
@apply font-light;
}
&.fi-font-normal {
@apply font-normal;
}
&.fi-font-medium {
@apply font-medium;
}
&.fi-font-semibold {
@apply font-semibold;
}
&.fi-font-bold {
@apply font-bold;
}
&.fi-font-extrabold {
@apply font-extrabold;
}
&.fi-font-black {
@apply font-black;
}
&.fi-size-lg {
@apply text-lg;
}
&.fi-color-neutral {
@apply text-gray-950 dark:text-white;
}
&.fi-color:not(.fi-color-neutral) {
@apply text-(--text) dark:text-(--dark-text);
}
&.fi-size-xs {
@apply text-xs;
}
&.fi-size-md {
@apply text-base;
}
}
}
@@ -0,0 +1,15 @@
.fi-sc-unordered-list {
@apply ms-3 list-disc text-sm sm:columns-2;
&.fi-size-xs {
@apply text-xs;
}
&.fi-size-md {
@apply text-base;
}
&.fi-size-lg {
@apply text-lg;
}
}
@@ -0,0 +1,181 @@
.fi-sc-wizard {
@apply flex flex-col;
& .fi-sc-wizard-header {
@apply grid md:grid-flow-col md:overflow-x-auto;
& .fi-sc-wizard-header-step {
@apply relative flex;
&:not(.fi-active) {
@apply hidden md:flex;
}
& .fi-sc-wizard-header-step-btn {
@apply flex h-full items-center gap-x-4 px-6 py-4 text-start;
& .fi-sc-wizard-header-step-icon-ctn {
@apply flex size-10 shrink-0 items-center justify-center rounded-full;
& .fi-sc-wizard-header-step-number {
@apply text-sm font-medium;
}
}
& .fi-sc-wizard-header-step-text {
@apply grid justify-items-start md:w-max md:max-w-60;
& .fi-sc-wizard-header-step-label {
@apply text-sm font-medium;
}
& .fi-sc-wizard-header-step-description {
@apply text-start text-sm text-gray-500 dark:text-gray-400;
}
}
}
& .fi-sc-wizard-header-step-separator {
@apply absolute end-0 hidden h-full w-5 text-gray-200 md:block rtl:rotate-180 dark:text-white/5;
}
&.fi-completed {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
@apply bg-primary-600 dark:bg-primary-500;
& .fi-icon {
@apply text-white;
}
}
& .fi-sc-wizard-header-step-text {
& .fi-sc-wizard-header-step-label {
@apply text-gray-950 dark:text-white;
}
}
}
}
&:not(.fi-completed) {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
@apply border-2;
}
}
&.fi-active {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
& .fi-icon {
@apply text-primary-600 dark:text-primary-500;
}
}
}
}
&:not(.fi-active) {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
& .fi-icon {
@apply text-gray-500 dark:text-gray-400;
}
}
}
}
}
&.fi-active {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
@apply border-primary-600 dark:border-primary-500;
& .fi-sc-wizard-header-step-number {
@apply text-primary-600 dark:text-primary-500;
}
}
& .fi-sc-wizard-header-step-text {
& .fi-sc-wizard-header-step-label {
@apply text-primary-700 dark:text-primary-400;
}
}
}
}
&:not(.fi-active) {
& .fi-sc-wizard-header-step-btn {
& .fi-sc-wizard-header-step-icon-ctn {
@apply border-gray-300 dark:border-gray-600;
& .fi-sc-wizard-header-step-number {
@apply text-gray-500 dark:text-gray-400;
}
& .fi-sc-wizard-header-step-text {
& .fi-sc-wizard-header-step-label {
@apply text-gray-500 dark:text-gray-400;
}
}
}
}
}
}
}
& .fi-sc-wizard-step {
@apply outline-hidden;
&:not(.fi-active) {
@apply invisible absolute h-0 overflow-hidden p-0;
}
}
&:not(.fi-sc-wizard-header-hidden) {
& .fi-sc-wizard-step {
&.fi-active {
@apply mt-6;
}
}
}
& .fi-sc-wizard-footer {
@apply flex items-center justify-between gap-x-3;
& > .fi-hidden {
@apply hidden;
}
& > .fi-disabled {
@apply pointer-events-none opacity-70;
}
}
&.fi-contained {
@apply rounded-xl bg-white shadow-xs ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10;
& .fi-sc-wizard-header {
@apply border-b border-gray-200 dark:border-white/10;
}
& .fi-sc-wizard-step {
&.fi-active {
@apply mt-0 p-6;
}
}
& .fi-sc-wizard-footer {
@apply px-6 pb-6;
}
}
&:not(.fi-contained) {
& .fi-sc-wizard-header {
@apply rounded-xl bg-white shadow-xs ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10;
}
& .fi-sc-wizard-footer {
@apply mt-6;
}
}
}
@@ -0,0 +1,12 @@
@import './components/actions.css' layer(components);
@import './components/flex.css' layer(components);
@import './components/form.css' layer(components);
@import './components/fused-group.css' layer(components);
@import './components/icon.css' layer(components);
@import './components/image.css' layer(components);
@import './components/section.css' layer(components);
@import './components/tabs.css' layer(components);
@import './components/text.css' layer(components);
@import './components/unordered-list.css' layer(components);
@import './components/wizard.css' layer(components);
@import './schema.css' layer(components);
@@ -0,0 +1,88 @@
.fi-sc {
@apply text-sm;
&.fi-inline {
@apply flex grow flex-wrap items-center;
}
&.fi-sc-has-gap {
@apply gap-6;
&.fi-sc-dense {
@apply gap-3;
}
}
&.fi-align-start,
&.fi-align-left {
@apply justify-start;
}
&.fi-align-center {
@apply justify-center;
}
&.fi-align-end,
&.fi-align-right {
@apply justify-end;
}
&.fi-align-between,
&.fi-align-justify {
@apply justify-between;
}
& > .fi-hidden {
@apply hidden;
}
& > .fi-grid-col {
&.fi-width-xs {
@apply max-w-xs;
}
&.fi-width-sm {
@apply max-w-sm;
}
&.fi-width-md {
@apply max-w-md;
}
&.fi-width-lg {
@apply max-w-lg;
}
&.fi-width-xl {
@apply max-w-xl;
}
&.fi-width-2xl {
@apply max-w-2xl;
}
&.fi-width-3xl {
@apply max-w-3xl;
}
&.fi-width-4xl {
@apply max-w-4xl;
}
&.fi-width-5xl {
@apply max-w-5xl;
}
&.fi-width-6xl {
@apply max-w-6xl;
}
&.fi-width-7xl {
@apply max-w-7xl;
}
& > .fi-sc-component {
@apply h-full;
}
}
}
@@ -0,0 +1,62 @@
export default () => ({
isSticky: false,
width: 0,
resizeObserver: null,
boundUpdateWidth: null,
init() {
const parent = this.$el.parentElement
if (!parent) {
return
}
this.updateWidth()
this.resizeObserver = new ResizeObserver(() => this.updateWidth())
this.resizeObserver.observe(parent)
this.boundUpdateWidth = this.updateWidth.bind(this)
window.addEventListener('resize', this.boundUpdateWidth)
},
enableSticky() {
this.isSticky = this.$el.getBoundingClientRect().top > 0
},
disableSticky() {
this.isSticky = false
},
updateWidth() {
const parent = this.$el.parentElement
if (!parent) {
return
}
const actionsComputedStyle = getComputedStyle(
this.$root.querySelector('.fi-ac'),
)
this.width =
parent.offsetWidth +
parseInt(actionsComputedStyle.marginInlineStart, 10) * -1 +
parseInt(actionsComputedStyle.marginInlineEnd, 10) * -1
},
destroy() {
if (this.resizeObserver) {
this.resizeObserver.disconnect()
this.resizeObserver = null
}
if (this.boundUpdateWidth) {
window.removeEventListener('resize', this.boundUpdateWidth)
this.boundUpdateWidth = null
}
},
})
@@ -0,0 +1,69 @@
export default function tabsSchemaComponent({
activeTab,
isTabPersistedInQueryString,
livewireId,
tab,
tabQueryStringKey,
}) {
return {
tab,
init() {
const tabs = this.getTabs()
const queryString = new URLSearchParams(window.location.search)
if (
isTabPersistedInQueryString &&
queryString.has(tabQueryStringKey) &&
tabs.includes(queryString.get(tabQueryStringKey))
) {
this.tab = queryString.get(tabQueryStringKey)
}
this.$watch('tab', () => this.updateQueryString())
if (!this.tab || !tabs.includes(this.tab)) {
this.tab = tabs[activeTab - 1]
}
Livewire.hook(
'commit',
({ component, commit, succeed, fail, respond }) => {
succeed(({ snapshot, effect }) => {
this.$nextTick(() => {
if (component.id !== livewireId) {
return
}
const tabs = this.getTabs()
if (!tabs.includes(this.tab)) {
this.tab = tabs[activeTab - 1] ?? this.tab
}
})
})
},
)
},
getTabs() {
if (!this.$refs.tabsData) {
return []
}
return JSON.parse(this.$refs.tabsData.value)
},
updateQueryString() {
if (!isTabPersistedInQueryString) {
return
}
const url = new URL(window.location.href)
url.searchParams.set(tabQueryStringKey, this.tab)
history.replaceState(null, document.title, url.toString())
},
}
}
@@ -0,0 +1,109 @@
export default function wizardSchemaComponent({
isSkippable,
isStepPersistedInQueryString,
key,
startStep,
stepQueryStringKey,
}) {
return {
step: null,
init() {
this.$watch('step', () => this.updateQueryString())
this.step = this.getSteps().at(startStep - 1)
this.autofocusFields()
},
async requestNextStep() {
await this.$wire.callSchemaComponentMethod(key, 'nextStep', {
currentStepIndex: this.getStepIndex(this.step),
})
},
goToNextStep() {
let nextStepIndex = this.getStepIndex(this.step) + 1
if (nextStepIndex >= this.getSteps().length) {
return
}
this.step = this.getSteps()[nextStepIndex]
this.autofocusFields()
this.scroll()
},
goToPreviousStep() {
let previousStepIndex = this.getStepIndex(this.step) - 1
if (previousStepIndex < 0) {
return
}
this.step = this.getSteps()[previousStepIndex]
this.autofocusFields()
this.scroll()
},
scroll() {
this.$nextTick(() => {
this.$refs.header?.children[
this.getStepIndex(this.step)
].scrollIntoView({ behavior: 'smooth', block: 'start' })
})
},
autofocusFields() {
this.$nextTick(() =>
this.$refs[`step-${this.step}`]
.querySelector('[autofocus]')
?.focus(),
)
},
getStepIndex(step) {
let index = this.getSteps().findIndex(
(indexedStep) => indexedStep === step,
)
if (index === -1) {
return 0
}
return index
},
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(stepKey) {
return (
isSkippable ||
this.getStepIndex(this.step) > this.getStepIndex(stepKey)
)
},
updateQueryString() {
if (!isStepPersistedInQueryString) {
return
}
const url = new URL(window.location.href)
url.searchParams.set(stepQueryStringKey, this.step)
history.replaceState(null, document.title, url.toString())
},
}
}
@@ -0,0 +1,150 @@
import actions from './components/actions.js'
const resolveRelativeStatePath = function (containerPath, path, isAbsolute) {
let containerPathCopy = containerPath
if (path.startsWith('/')) {
isAbsolute = true
path = path.slice(1)
}
if (isAbsolute) {
return path
}
while (path.startsWith('../')) {
containerPathCopy = containerPathCopy.includes('.')
? containerPathCopy.slice(0, containerPathCopy.lastIndexOf('.'))
: null
path = path.slice(3)
}
if (['', null, undefined].includes(containerPathCopy)) {
return path
}
if (['', null, undefined].includes(path)) {
return containerPathCopy
}
return `${containerPathCopy}.${path}`
}
const findClosestLivewireComponent = (el) => {
let closestRoot = Alpine.findClosest(el, (i) => i.__livewire)
if (!closestRoot) {
throw 'Could not find Livewire component in DOM tree.'
}
return closestRoot.__livewire
}
document.addEventListener('alpine:init', () => {
window.Alpine.data('filamentSchema', ({ livewireId }) => ({
handleFormValidationError(event) {
if (event.detail.livewireId !== livewireId) {
return
}
this.$nextTick(() => {
let error = this.$el.querySelector('[data-validation-error]')
if (!error) {
return
}
let elementToExpand = error
while (elementToExpand) {
elementToExpand.dispatchEvent(new CustomEvent('expand'))
elementToExpand = elementToExpand.parentNode
}
setTimeout(
() =>
error.closest('[data-field-wrapper]').scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'start',
}),
200,
)
})
},
isStateChanged(state, old) {
if (state === undefined) {
return false
}
try {
return JSON.stringify(state) !== JSON.stringify(old)
} catch {
return state !== old
}
},
}))
window.Alpine.data(
'filamentSchemaComponent',
({ path, containerPath, $wire }) => ({
$statePath: path,
$get: (path, isAbsolute) => {
return $wire.$get(
resolveRelativeStatePath(containerPath, path, isAbsolute),
)
},
$set: (path, state, isAbsolute, isLive = false) => {
return $wire.$set(
resolveRelativeStatePath(containerPath, path, isAbsolute),
state,
isLive,
)
},
get $state() {
return $wire.$get(path)
},
}),
)
window.Alpine.data('filamentActionsSchemaComponent', actions)
Livewire.hook('commit', ({ component, commit, respond, succeed, fail }) => {
succeed(({ snapshot, effects }) => {
effects.dispatches?.forEach((dispatch) => {
if (!dispatch.params?.awaitSchemaComponent) {
return
}
let els = Array.from(
component.el.querySelectorAll(
`[wire\\:partial="schema-component::${dispatch.params.awaitSchemaComponent}"]`,
),
).filter((el) => findClosestLivewireComponent(el) === component)
if (els.length === 1) {
return
}
if (els.length > 1) {
throw `Multiple schema components found with key [${dispatch.params.awaitSchemaComponent}].`
}
window.addEventListener(
`schema-component-${component.id}-${dispatch.params.awaitSchemaComponent}-loaded`,
() => {
window.dispatchEvent(
new CustomEvent(dispatch.name, {
detail: dispatch.params,
}),
)
},
{ once: true },
)
})
})
})
})
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'ወደ ኋላ',
],
'next_step' => [
'label' => 'ቀጣይ',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'الخطوة السابقة',
],
'next_step' => [
'label' => 'الخطوة التالية',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Geri',
],
'next_step' => [
'label' => 'İrəli',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Назад',
],
'next_step' => [
'label' => 'Напред',
],
],
],
];
@@ -0,0 +1,238 @@
<?php
return [
'builder' => [
'actions' => [
'clone' => [
'label' => 'অনুলিপি করুন',
],
'add' => [
'label' => ':label এ যোগ করুন',
],
'add_between' => [
'label' => 'প্রবেশ করান',
],
'delete' => [
'label' => 'মুছে ফেলুন',
],
'reorder' => [
'label' => 'সরান',
],
'move_down' => [
'label' => 'নিচে সরান',
],
'move_up' => [
'label' => 'উপরে সরান',
],
'collapse' => [
'label' => 'ছোট করুন',
],
'expand' => [
'label' => 'বড় করুন',
],
'collapse_all' => [
'label' => 'সব ছোট করুন',
],
'expand_all' => [
'label' => 'সব বড় করুন',
],
],
],
'checkbox_list' => [
'actions' => [
'select_all' => [
'label' => 'সব নির্বাচিত করুন',
],
'deselect_all' => [
'label' => 'সব অনির্বাচিত করুন',
],
],
],
'key_value' => [
'actions' => [
'add' => [
'label' => 'সারি যোগ করুন',
],
'delete' => [
'label' => 'সারি মুছে ফেলুন',
],
'reorder' => [
'label' => 'সারি পুনর্বিন্যাস করুন',
],
],
'fields' => [
'key' => [
'label' => 'চাবি',
],
'value' => [
'label' => 'মান',
],
],
],
'repeater' => [
'actions' => [
'add' => [
'label' => ':label এ যোগ করুন',
],
'delete' => [
'label' => 'মুছে ফেলুন',
],
'clone' => [
'label' => 'অনুলিপি করুন',
],
'reorder' => [
'label' => 'সরান',
],
'move_down' => [
'label' => 'নিচে সরান',
],
'move_up' => [
'label' => 'উপরে সরান',
],
'collapse' => [
'label' => 'ছোট করুন',
],
'expand' => [
'label' => 'বড় করুন',
],
'collapse_all' => [
'label' => 'সব ছোট করুন',
],
'expand_all' => [
'label' => 'সব বড় করুন',
],
],
],
'rich_editor' => [
'dialogs' => [
'link' => [
'actions' => [
'link' => 'লিংক',
'unlink' => 'আনলিংক',
],
'label' => 'ইউআরএল',
'placeholder' => 'ইউআরএল দিন',
],
],
'tools' => [
'attach_files' => 'নথি যোগ করুন',
'blockquote' => 'ব্লককোট',
'bold' => 'বোল্ড',
'bullet_list' => 'বুলেট তালিকা',
'code_block' => 'কোড ব্লক',
'h1' => 'শিরোনাম',
'h2' => 'শিরোনাম',
'h3' => 'উপশিরোনাম',
'italic' => 'তির্যক',
'link' => 'লিংক',
'ordered_list' => 'সংখ্যাযুক্ত তালিকা',
'redo' => 'পরবর্তী',
'strike' => 'স্ট্রাইকথ্রু',
'undo' => 'পূর্বাবস্থা',
],
],
'select' => [
'actions' => [
'create_option' => [
'modal' => [
'heading' => 'তৈরি করুন',
'actions' => [
'create' => [
'label' => 'তৈরি করুন',
],
],
],
],
],
'boolean' => [
'true' => 'হ্যাঁ',
'false' => 'না',
],
'loading_message' => 'লোড হচ্ছে...',
'max_items_message' => 'মাত্র :count টা নির্বাচন করা যাবে।',
'no_search_results_message' => 'খুঁজে পাওয়া যায়নি।',
'placeholder' => 'নির্বাচন করুন',
'searching_message' => 'খুঁজুন...',
'search_prompt' => 'লিখুন...',
],
'tags_input' => [
'placeholder' => 'নতুন ট্যাগ',
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Nazad',
],
'next_step' => [
'label' => 'Dalje',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Enrere',
],
'next_step' => [
'label' => 'Endavant',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'پێشتر',
],
'next_step' => [
'label' => 'دواتر',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Zpět',
],
'next_step' => [
'label' => 'Další',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Yn ôl',
],
'next_step' => [
'label' => 'Nesaf',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Tilbage',
],
'next_step' => [
'label' => 'Næste',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Zurück',
],
'next_step' => [
'label' => 'Weiter',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Πίσω',
],
'next_step' => [
'label' => 'Επόμενο',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Back',
],
'next_step' => [
'label' => 'Next',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Anterior',
],
'next_step' => [
'label' => 'Siguiente',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Aurrekoa',
],
'next_step' => [
'label' => 'Hurrengoa',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'قبلی',
],
'next_step' => [
'label' => 'بعدی',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Edellinen',
],
'next_step' => [
'label' => 'Seuraava',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Précédent',
],
'next_step' => [
'label' => 'Suivant',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'הקודם',
],
'next_step' => [
'label' => 'הבא',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Natrag',
],
'next_step' => [
'label' => 'Naprijed',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Előző lépés',
],
'next_step' => [
'label' => 'Következő lépés',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Նախորդը',
],
'next_step' => [
'label' => 'Հաջորդը',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Sebelumnya',
],
'next_step' => [
'label' => 'Selanjutnya',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Precedente',
],
'next_step' => [
'label' => 'Successivo',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => '前へ',
],
'next_step' => [
'label' => '次へ',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'უკან',
],
'next_step' => [
'label' => 'შემდეგი',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'ត្រឡប់មកវិញ',
],
'next_step' => [
'label' => 'បន្ទាប់',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => '이전',
],
'next_step' => [
'label' => '다음',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'پێشوو',
],
'next_step' => [
'label' => 'دواتر',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Atgal',
],
'next_step' => [
'label' => 'Pirmyn',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Lêtna',
],
'next_step' => [
'label' => 'A dawt',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Iepriekšējais',
],
'next_step' => [
'label' => 'Nākamais',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Буцах',
],
'next_step' => [
'label' => 'Дараагийн',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Sebelum',
],
'next_step' => [
'label' => 'Seterus',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Tilbake',
],
'next_step' => [
'label' => 'Neste',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'पछाडि',
],
'next_step' => [
'label' => 'अर्को',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Vorige',
],
'next_step' => [
'label' => 'Volgende',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Poprzedni',
],
'next_step' => [
'label' => 'Następny',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Voltar',
],
'next_step' => [
'label' => 'Próximo',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Voltar',
],
'next_step' => [
'label' => 'Próximo',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Pasul anterior',
],
'next_step' => [
'label' => 'Pasul următor',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Назад',
],
'next_step' => [
'label' => 'Далее',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Spať',
],
'next_step' => [
'label' => 'Ďalej',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Pas',
],
'next_step' => [
'label' => 'Para',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Назад',
],
'next_step' => [
'label' => 'Напред',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Nazad',
],
'next_step' => [
'label' => 'Napred',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Föregående',
],
'next_step' => [
'label' => 'Nästa',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Nyuma',
],
'next_step' => [
'label' => 'Mbele',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'ย้อนกลับ',
],
'next_step' => [
'label' => 'ถัดไป',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Geri',
],
'next_step' => [
'label' => 'İleri',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Назад',
],
'next_step' => [
'label' => 'Далі',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'پیچھے جائیں',
],
'next_step' => [
'label' => 'اگلا مرحلہ',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Orqaga',
],
'next_step' => [
'label' => 'Keyingi',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => 'Quay lại',
],
'next_step' => [
'label' => 'Tiếp theo',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => '上一步',
],
'next_step' => [
'label' => '下一步',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => '返回',
],
'next_step' => [
'label' => '繼續',
],
],
],
];
@@ -0,0 +1,21 @@
<?php
return [
'wizard' => [
'actions' => [
'previous_step' => [
'label' => '返回',
],
'next_step' => [
'label' => '繼續',
],
],
],
];
@@ -0,0 +1,60 @@
@php
use Filament\Support\Enums\VerticalAlignment;
$actions = $getChildSchema()->getComponents();
$alignment = $getAlignment();
$isFullWidth = $isFullWidth();
$isSticky = $isSticky();
$verticalAlignment = $getVerticalAlignment();
if (! $verticalAlignment instanceof VerticalAlignment) {
$verticalAlignment = filled($verticalAlignment) ? (VerticalAlignment::tryFrom($verticalAlignment) ?? $verticalAlignment) : null;
}
@endphp
<div
@if ($isSticky)
x-data="filamentActionsSchemaComponent()"
x-intersect:enter.half="disableSticky"
x-intersect:leave="enableSticky"
x-bind:class="{ 'fi-sticky': isSticky }"
@endif
{{
$attributes
->merge([
'id' => $getId(),
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class([
'fi-sc-actions',
($verticalAlignment instanceof VerticalAlignment) ? "fi-vertical-align-{$verticalAlignment->value}" : $verticalAlignment,
])
}}
>
@if (filled($label = $getLabel()))
<div class="fi-sc-actions-label-ctn">
{{ $getChildSchema($schemaComponent::BEFORE_LABEL_SCHEMA_KEY) }}
<div class="fi-sc-actions-label">
{{ $label }}
</div>
{{ $getChildSchema($schemaComponent::AFTER_LABEL_SCHEMA_KEY) }}
</div>
@endif
@if ($aboveContentContainer = $getChildSchema($schemaComponent::ABOVE_CONTENT_SCHEMA_KEY)?->toHtmlString())
{{ $aboveContentContainer }}
@endif
<x-filament::actions
:actions="$actions"
:alignment="$alignment"
:full-width="$isFullWidth"
:x-bind:style="$isSticky ? 'isSticky ? `width: ${width}px;` : \'\'' : null"
/>
@if ($belowContentContainer = $getChildSchema($schemaComponent::BELOW_CONTENT_SCHEMA_KEY)?->toHtmlString())
{{ $belowContentContainer }}
@endif
</div>
@@ -0,0 +1,27 @@
@php
$description = $getDescription();
$footer = $getChildSchema($schemaComponent::FOOTER_SCHEMA_KEY)?->toHtmlString();
$heading = $getHeading();
$headingTag = $getHeadingTag();
$icon = $getIcon();
$iconColor = $getIconColor();
$iconSize = $getIconSize();
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-sc-empty-state'])
}}
>
<x-filament::empty-state
:description="$description"
:footer="$footer"
:heading="$heading"
:heading-tag="$headingTag"
:icon="$icon"
:icon-color="$iconColor"
:icon-size="$iconSize"
/>
</div>
@@ -0,0 +1,24 @@
@php
$extraAttributes = $getExtraAttributes();
$id = $getId();
$isLabelHidden = $isLabelHidden();
$label = $getLabel();
$isContained = $isContained();
@endphp
<x-filament::fieldset
:contained="$isContained"
:label="$label"
:label-hidden="$isLabelHidden"
:required="isset($isMarkedAsRequired) ? $isMarkedAsRequired() : false"
:attributes="
\Filament\Support\prepare_inherited_attributes($attributes)
->merge([
'id' => $id,
], escape: false)
->merge($extraAttributes, escape: false)
->class(['fi-sc-fieldset'])
"
>
{{ $getChildSchema() }}
</x-filament::fieldset>
@@ -0,0 +1,71 @@
@php
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Schemas\Components\Component;
use Filament\Support\Enums\VerticalAlignment;
$statePath = $getStatePath();
$fromBreakpoint = $getFromBreakpoint();
$verticalAlignment = $getVerticalAlignment();
if (! $verticalAlignment instanceof VerticalAlignment) {
$verticalAlignment = filled($verticalAlignment) ? (VerticalAlignment::tryFrom($verticalAlignment) ?? $verticalAlignment) : null;
}
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-sc-flex',
'fi-dense' => $isDense(),
'fi-from-' . ($fromBreakpoint ?? 'default'),
($verticalAlignment instanceof VerticalAlignment) ? "fi-vertical-align-{$verticalAlignment->value}" : $verticalAlignment,
])
}}
>
@foreach ($getChildSchema()->getComponents() as $component)
@if (($component instanceof Action) || ($component instanceof ActionGroup))
<div>
{{ $component }}
</div>
@else
@php
$hiddenJs = $component->getHiddenJs();
$visibleJs = $component->getVisibleJs();
$componentStatePath = $component->getStatePath();
@endphp
<div
x-data="filamentSchemaComponent({
path: @js($componentStatePath),
containerPath: @js($statePath),
$wire,
})"
@if ($afterStateUpdatedJs = $schemaComponent->getAfterStateUpdatedJs())
x-init="{!! implode(';', array_map(
fn (string $js): string => '$wire.watch(' . Js::from($componentStatePath) . ', ($state, $old) => isStateChanged($state, $old) && eval(' . Js::from($js) . '))',
$afterStateUpdatedJs,
)) !!}"
@endif
@if (filled($visibilityJs = match ([filled($hiddenJs), filled($visibleJs)]) {
[true, true] => "(! ({$hiddenJs})) && ({$visibleJs})",
[true, false] => "! ({$hiddenJs})",
[false, true] => $visibleJs,
default => null,
}))
x-bind:class="{ 'fi-hidden': ! ({!! $visibilityJs !!}) }"
x-cloak
@endif
@class([
'fi-growable' => ($component instanceof Component) && $component->canGrow(),
])
>
{{ $component }}
</div>
@endif
@endforeach
</div>
@@ -0,0 +1,20 @@
<form
{{
$attributes
->merge([
'id' => $getId(),
'wire:submit' => $getLivewireSubmitHandler(),
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class([
'fi-sc-form',
'fi-dense' => $isDense(),
])
}}
>
{{ $getChildSchema($schemaComponent::HEADER_SCHEMA_KEY) }}
{{ $getChildSchema() }}
{{ $getChildSchema($schemaComponent::FOOTER_SCHEMA_KEY) }}
</form>
@@ -0,0 +1,73 @@
@php
use Filament\Forms\Components\Contracts\HasNestedRecursiveValidationRules;
use Filament\Forms\Components\Field;
$fieldWrapperView = $getFieldWrapperView();
$errorMessages = null;
$errorMessage = null;
foreach ($getChildComponentContainer()->getComponents() as $childComponent) {
if (! ($childComponent instanceof Field)) {
continue;
}
$statePath = $childComponent->getStatePath();
if (blank($statePath)) {
continue;
}
if ($errors->has($statePath)) {
if ($childComponent->shouldShowAllValidationMessages()) {
$errorMessages = $errors->get($statePath);
$shouldShowAllValidationMessages = true;
} else {
$errorMessage = $errors->first($statePath);
}
$areHtmlValidationMessagesAllowed = $childComponent->areHtmlValidationMessagesAllowed();
break;
}
if (! ($childComponent instanceof HasNestedRecursiveValidationRules)) {
continue;
}
if ($errors->has("{$statePath}.*")) {
if ($childComponent->shouldShowAllValidationMessages()) {
$errorMessages = $errors->get("{$statePath}.*");
$shouldShowAllValidationMessages = true;
} else {
$errorMessage = $errors->first("{$statePath}.*");
}
$areHtmlValidationMessagesAllowed = $childComponent->areHtmlValidationMessagesAllowed();
break;
}
}
@endphp
<x-dynamic-component
:component="$fieldWrapperView"
:error-message="$errorMessage"
:error-messages="$errorMessages"
:are-html-error-messages-allowed="$areHtmlValidationMessagesAllowed ?? false"
:should-show-all-validation-messages="$shouldShowAllValidationMessages ?? false"
:field="$schemaComponent"
>
<div
{{
$attributes
->merge([
'id' => $getId(),
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class(['fi-sc-fused-group'])
}}
>
{{ $getChildSchema() }}
</div>
</x-dynamic-component>
@@ -0,0 +1,11 @@
<div
{{
$attributes
->merge([
'id' => $getId(),
], escape: false)
->merge($getExtraAttributes(), escape: false)
}}
>
{{ $getChildSchema() }}
</div>
@@ -0,0 +1,31 @@
@php
use Filament\Support\Enums\Alignment;
$alignment = $getAlignment();
$height = $getImageHeight() ?? '8rem';
$width = $getImageWidth();
$tooltip = $getTooltip();
if (! $alignment instanceof Alignment) {
$alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
}
@endphp
<img
alt="{{ $getAlt() }}"
src="{{ $getUrl() }}"
@if (filled($tooltip))
x-tooltip="{ content: @js($tooltip), theme: $store.theme, allowHTML: @js($tooltip instanceof \Illuminate\Contracts\Support\Htmlable) }"
@endif
{{
$getExtraAttributeBag()
->class([
'fi-sc-image',
($alignment instanceof Alignment) ? "fi-align-{$alignment->value}" : $alignment,
])
->style([
"height: {$height}" => $height,
"width: {$width}" => $width,
])
}}
/>
@@ -0,0 +1,27 @@
@php
$extraAttributes = $getExtraAttributes();
$id = $getId();
@endphp
@if (filled($id) || filled($extraAttributes))
{!! '<div' !!}
{{-- Avoid formatting issues with unclosed elements --}}
{{
$attributes
->merge([
'id' => $id,
], escape: false)
->merge($extraAttributes, escape: false)
}}
>
@endif
@if (filled($key = $getLivewireKey()))
@livewire($getComponent(), $getComponentProperties(), key($key))
@else
@livewire($getComponent(), $getComponentProperties())
@endif
@if (filled($id) || filled($extraAttributes))
{!! '</div>' !!}
{{-- Avoid formatting issues with unclosed elements --}}
@endif
@@ -0,0 +1,76 @@
@php
$afterHeader = $getChildSchema($schemaComponent::AFTER_HEADER_SCHEMA_KEY)?->toHtmlString();
$isAside = $isAside();
$isCollapsed = $isCollapsed();
$isCollapsible = $isCollapsible();
$isCompact = $isCompact();
$isContained = $isContained();
$isDivided = $isDivided();
$isFormBefore = $isFormBefore();
$description = $getDescription();
$footer = $getChildSchema($schemaComponent::FOOTER_SCHEMA_KEY)?->toHtmlString();
$heading = $getHeading();
$headingTag = $getHeadingTag();
$icon = $getIcon();
$iconColor = $getIconColor();
$iconSize = $getIconSize();
$shouldPersistCollapsed = $shouldPersistCollapsed();
$isSecondary = $isSecondary();
$id = $getId();
@endphp
<div
{{
$attributes
->merge([
'id' => $id,
], escape: false)
->merge($getExtraAttributes(), escape: false)
->merge($getExtraAlpineAttributes(), escape: false)
->class(['fi-sc-section'])
}}
>
@if (filled($label = $getLabel()))
<div class="fi-sc-section-label-ctn">
{{ $getChildSchema($schemaComponent::BEFORE_LABEL_SCHEMA_KEY) }}
<div class="fi-sc-section-label">
{{ $label }}
</div>
{{ $getChildSchema($schemaComponent::AFTER_LABEL_SCHEMA_KEY) }}
</div>
@endif
@if ($aboveContentContainer = $getChildSchema($schemaComponent::ABOVE_CONTENT_SCHEMA_KEY)?->toHtmlString())
{{ $aboveContentContainer }}
@endif
<x-filament::section
:after-header="$afterHeader"
:aside="$isAside"
:collapsed="$isCollapsed"
:collapse-id="$id"
:collapsible="$isCollapsible && (! $isAside)"
:compact="$isCompact"
:contained="$isContained"
:content-before="$isFormBefore"
:description="$description"
:divided="$isDivided"
:footer="$footer"
:has-content-el="false"
:heading="$heading"
:heading-tag="$headingTag"
:icon="$icon"
:icon-color="$iconColor"
:icon-size="$iconSize"
:persist-collapsed="$shouldPersistCollapsed"
:secondary="$isSecondary"
>
{{ $getChildSchema()->gap(! $isDivided)->extraAttributes(['class' => 'fi-section-content']) }}
</x-filament::section>
@if ($belowContentContainer = $getChildSchema($schemaComponent::BELOW_CONTENT_SCHEMA_KEY)?->toHtmlString())
{{ $belowContentContainer }}
@endif
</div>
@@ -0,0 +1,194 @@
@php
use Filament\Schemas\Components\Tabs\Tab;
$activeTab = $getActiveTab();
$isContained = $isContained();
$isVertical = $isVertical();
$label = $getLabel();
$livewireProperty = $getLivewireProperty();
$renderHookScopes = $getRenderHookScopes();
$id = $getId();
@endphp
@if (blank($livewireProperty))
<div
x-load
x-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('tabs', 'filament/schemas') }}"
x-data="tabsSchemaComponent({
activeTab: @js($activeTab),
isTabPersistedInQueryString: @js($isTabPersistedInQueryString()),
livewireId: @js($this->getId()),
tab: @if ($isTabPersisted() && filled($id)) $persist(null).as(@js($id)) @else @js(null) @endif,
tabQueryStringKey: @js($getTabQueryStringKey()),
})"
wire:ignore.self
{{
$attributes
->merge([
'id' => $id,
'wire:key' => $getLivewireKey() . '.container',
], escape: false)
->merge($getExtraAttributes(), escape: false)
->merge($getExtraAlpineAttributes(), escape: false)
->class([
'fi-sc-tabs',
'fi-contained' => $isContained,
'fi-vertical' => $isVertical,
])
}}
>
<input
type="hidden"
value="{{
collect($getChildSchema()->getComponents())
->filter(static fn (Tab $tab): bool => $tab->isVisible())
->map(static fn (Tab $tab) => $tab->getKey(isAbsolute: false))
->values()
->toJson()
}}"
x-ref="tabsData"
/>
<x-filament::tabs
:contained="$isContained"
:label="$label"
:vertical="$isVertical"
x-cloak
>
@foreach ($getStartRenderHooks() as $startRenderHook)
{{ \Filament\Support\Facades\FilamentView::renderHook($startRenderHook, scopes: $renderHookScopes) }}
@endforeach
@foreach ($getChildSchema()->getComponents() as $tab)
@php
$tabKey = $tab->getKey(isAbsolute: false);
$tabBadge = $tab->getBadge();
$tabBadgeColor = $tab->getBadgeColor();
$tabBadgeIcon = $tab->getBadgeIcon();
$tabBadgeIconPosition = $tab->getBadgeIconPosition();
$tabBadgeTooltip = $tab->getBadgeTooltip();
$tabIcon = $tab->getIcon();
$tabIconPosition = $tab->getIconPosition();
$tabExtraAttributeBag = $tab->getExtraAttributeBag();
$tabHiddenJs = $tab->getHiddenJs();
$tabVisibleJs = $tab->getVisibleJs();
$tabVisibilityJs = match ([filled($tabHiddenJs), filled($tabVisibleJs)]) {
[true, true] => "(! ({$tabHiddenJs})) && ({$tabVisibleJs})",
[true, false] => "! ({$tabHiddenJs})",
[false, true] => $tabVisibleJs,
default => null,
};
@endphp
<x-filament::tabs.item
:alpine-active="'tab === \'' . $tabKey . '\''"
:badge="$tabBadge"
:badge-color="$tabBadgeColor"
:badge-icon="$tabBadgeIcon"
:badge-icon-position="$tabBadgeIconPosition"
:badge-tooltip="$tabBadgeTooltip"
:icon="$tabIcon"
:icon-position="$tabIconPosition"
:x-on:click="'tab = \'' . $tabKey . '\''"
:x-show="$tabVisibilityJs"
:x-cloak="$tabVisibilityJs !== null"
:attributes="$tabExtraAttributeBag"
>
{{ $tab->getLabel() }}
</x-filament::tabs.item>
@endforeach
@foreach ($getEndRenderHooks() as $endRenderHook)
{{ \Filament\Support\Facades\FilamentView::renderHook($endRenderHook, scopes: $renderHookScopes) }}
@endforeach
</x-filament::tabs>
@foreach ($getChildSchema()->getComponents() as $tab)
@php
$tabHiddenJs = $tab->getHiddenJs();
$tabVisibleJs = $tab->getVisibleJs();
$tabVisibilityJs = match ([filled($tabHiddenJs), filled($tabVisibleJs)]) {
[true, true] => "(! ({$tabHiddenJs})) && ({$tabVisibleJs})",
[true, false] => "! ({$tabHiddenJs})",
[false, true] => $tabVisibleJs,
default => null,
};
@endphp
@if ($tabVisibilityJs)
<div x-show="{!! $tabVisibilityJs !!}" x-cloak>
{{ $tab }}
</div>
@else
{{ $tab }}
@endif
@endforeach
</div>
@else
@php
$activeTab = strval($this->{$livewireProperty});
@endphp
<div
{{
$attributes
->merge([
'id' => $id,
'wire:key' => $getLivewireKey() . '.container',
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class([
'fi-sc-tabs',
'fi-contained' => $isContained,
'fi-vertical' => $isVertical,
])
}}
>
<x-filament::tabs
:contained="$isContained"
:label="$label"
:vertical="$isVertical"
>
@foreach ($getStartRenderHooks() as $startRenderHook)
{{ \Filament\Support\Facades\FilamentView::renderHook($startRenderHook, scopes: $renderHookScopes) }}
@endforeach
@foreach ($getChildSchema()->getComponents(withOriginalKeys: true) as $tabKey => $tab)
@php
$tabBadge = $tab->getBadge();
$tabBadgeColor = $tab->getBadgeColor();
$tabBadgeIcon = $tab->getBadgeIcon();
$tabBadgeIconPosition = $tab->getBadgeIconPosition();
$tabBadgeTooltip = $tab->getBadgeTooltip();
$tabIcon = $tab->getIcon();
$tabIconPosition = $tab->getIconPosition();
$tabExtraAttributeBag = $tab->getExtraAttributeBag();
$tabKey = strval($tabKey);
@endphp
<x-filament::tabs.item
:active="$activeTab === $tabKey"
:badge="$tabBadge"
:badge-color="$tabBadgeColor"
:badge-icon="$tabBadgeIcon"
:badge-icon-position="$tabBadgeIconPosition"
:badge-tooltip="$tabBadgeTooltip"
:icon="$tabIcon"
:icon-position="$tabIconPosition"
:wire:click="'$set(\'' . $livewireProperty . '\', ' . (filled($tabKey) ? ('\'' . $tabKey . '\'') : 'null') . ')'"
:attributes="$tabExtraAttributeBag"
>
{{ $tab->getLabel() ?? $this->generateTabLabel($tabKey) }}
</x-filament::tabs.item>
@endforeach
@foreach ($getEndRenderHooks() as $endRenderHook)
{{ \Filament\Support\Facades\FilamentView::renderHook($endRenderHook, scopes: $renderHookScopes) }}
@endforeach
</x-filament::tabs>
@foreach ($getChildSchema()->getComponents(withOriginalKeys: true) as $tabKey => $tab)
{{ $tab->key($tabKey) }}
@endforeach
</div>
@endif
@@ -0,0 +1,49 @@
@php
$id = $getId();
$key = $getKey(isAbsolute: false);
$tabs = $getContainer()->getParentComponent();
$isContained = $tabs->isContained();
$livewireProperty = $tabs->getLivewireProperty();
$childSchema = $getChildSchema();
@endphp
@if (! empty($childSchema->getComponents()))
@if (blank($livewireProperty))
<div
x-bind:class="{
'fi-active': tab === @js($key),
}"
x-on:expand="tab = @js($key)"
{{
$attributes
->merge([
'aria-labelledby' => $id,
'id' => $id,
'role' => 'tabpanel',
'wire:key' => $getLivewireKey() . '.container',
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class(['fi-sc-tabs-tab'])
}}
>
{{ $childSchema }}
</div>
@elseif (strval($this->{$livewireProperty}) === strval($key))
<div
{{
$attributes
->merge([
'aria-labelledby' => $id,
'id' => $id,
'role' => 'tabpanel',
'wire:key' => $getLivewireKey() . '.container',
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class(['fi-sc-tabs-tab fi-active'])
}}
>
{{ $childSchema }}
</div>
@endif
@endif
@@ -0,0 +1,78 @@
@php
use Filament\Schemas\View\Components\TextComponent;
use Filament\Support\Enums\FontFamily;
use Filament\Support\Enums\FontWeight;
use Filament\Support\RawJs;
$color = $getColor();
$content = $getContent();
$icon = $getIcon();
$iconPosition = $getIconPosition();
$iconSize = $getIconSize();
$size = $getSize();
$tooltip = $getTooltip();
$weight = $getWeight();
$fontFamily = $getFontFamily();
$copyableState = $getCopyableState($content) ?? $content;
$copyMessage = $getCopyMessage($copyableState);
$copyMessageDuration = $getCopyMessageDuration($copyableState);
$isCopyable = $isCopyable($copyableState);
@endphp
@if ($isBadge())
<x-filament::badge
:color="$color"
:icon="$icon"
:icon-position="$iconPosition"
:icon-size="$iconSize"
:size="$size instanceof \Filament\Support\Enums\TextSize ? $size->value : $size"
:x-on:click="
$isCopyable ? '
window.navigator.clipboard.writeText(' . \Illuminate\Support\Js::from($copyableState) . ')
$tooltip(' . \Illuminate\Support\Js::from($copyMessage) . ', {
theme: $store.theme,
timeout: ' . \Illuminate\Support\Js::from($copyMessageDuration) . ',
})
' : null
"
:tag="$isCopyable ? 'button' : 'span'"
:tooltip="$tooltip"
:attributes="\Filament\Support\prepare_inherited_attributes($getExtraAttributeBag()->class(['fi-sc-text']))"
>
{{ $content }}
</x-filament::badge>
@else
<span
@if ($isCopyable)
x-on:click="
window.navigator.clipboard.writeText(@js($copyableState))
$tooltip(@js($copyMessage), {
theme: $store.theme,
timeout: @js($copyMessageDuration),
})
"
@endif
@if (filled($tooltip))
x-tooltip="{
content: @js($tooltip),
theme: $store.theme,
allowHTML: @js($tooltip instanceof \Illuminate\Contracts\Support\Htmlable),
}"
@endif
{{
(new \Illuminate\View\ComponentAttributeBag)
->color(TextComponent::class, $color)
->class([
'fi-sc-text',
'fi-copyable' => $isCopyable,
($size instanceof \BackedEnum) ? "fi-size-{$size->value}" : $size,
($weight instanceof FontWeight) ? "fi-font-{$weight->value}" : $weight,
($fontFamily instanceof FontFamily) ? "fi-font-{$fontFamily->value}" : $fontFamily,
])
->merge($getExtraAttributes(), escape: false)
}}
>
{{ $content }}
</span>
@endif
@@ -0,0 +1,14 @@
<ul
{{
$getExtraAttributeBag()->class([
'fi-sc-unordered-list',
(($size = $getSize()) instanceof \Filament\Support\Enums\TextSize) ? "fi-size-{$size->value}" : $size,
])
}}
>
@foreach ($getChildSchema()->getComponents() as $component)
<li>
{{ $component }}
</li>
@endforeach
</ul>
@@ -0,0 +1,184 @@
@php
$isContained = $isContained();
$key = $getKey();
$previousAction = $getAction('previous');
$nextAction = $getAction('next');
$steps = $getChildSchema()->getComponents();
$isHeaderHidden = $isHeaderHidden();
@endphp
<div
x-load
x-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('wizard', 'filament/schemas') }}"
x-data="wizardSchemaComponent({
isSkippable: @js($isSkippable()),
isStepPersistedInQueryString: @js($isStepPersistedInQueryString()),
key: @js($key),
startStep: @js($getStartStep()),
stepQueryStringKey: @js($getStepQueryStringKey()),
})"
x-on:next-wizard-step.window="if ($event.detail.key === @js($key)) goToNextStep()"
wire:ignore.self
{{
$attributes
->merge([
'id' => $getId(),
], escape: false)
->merge($getExtraAttributes(), escape: false)
->merge($getExtraAlpineAttributes(), escape: false)
->class([
'fi-sc-wizard',
'fi-contained' => $isContained,
'fi-sc-wizard-header-hidden' => $isHeaderHidden,
])
}}
>
<input
type="hidden"
value="{{
collect($steps)
->filter(static fn (\Filament\Schemas\Components\Wizard\Step $step): bool => $step->isVisible())
->map(static fn (\Filament\Schemas\Components\Wizard\Step $step): ?string => $step->getKey())
->values()
->toJson()
}}"
x-ref="stepsData"
/>
@if (! $isHeaderHidden)
<ol
@if (filled($label = $getLabel()))
aria-label="{{ $label }}"
@endif
role="list"
x-cloak
x-ref="header"
class="fi-sc-wizard-header"
>
@foreach ($steps as $step)
<li
class="fi-sc-wizard-header-step"
x-bind:class="{
'fi-active': getStepIndex(step) === {{ $loop->index }},
'fi-completed': getStepIndex(step) > {{ $loop->index }},
}"
>
<button
type="button"
x-bind:aria-current="getStepIndex(step) === {{ $loop->index }} ? 'step' : null"
x-on:click="step = @js($step->getKey())"
x-bind:disabled="! isStepAccessible(@js($step->getKey())) || @js($previousAction->isDisabled())"
role="step"
class="fi-sc-wizard-header-step-btn"
>
<div class="fi-sc-wizard-header-step-icon-ctn">
@php
$completedIcon = $step->getCompletedIcon();
@endphp
{{
\Filament\Support\generate_icon_html(
$completedIcon ?? \Filament\Support\Icons\Heroicon::OutlinedCheck,
alias: filled($completedIcon) ? null : \Filament\Schemas\View\SchemaIconAlias::COMPONENTS_WIZARD_COMPLETED_STEP,
attributes: new \Illuminate\View\ComponentAttributeBag([
'x-cloak' => 'x-cloak',
'x-show' => "getStepIndex(step) > {$loop->index}",
]),
size: \Filament\Support\Enums\IconSize::Large,
)
}}
@if (filled($icon = $step->getIcon()))
{{
\Filament\Support\generate_icon_html(
$icon,
attributes: new \Illuminate\View\ComponentAttributeBag([
'x-cloak' => 'x-cloak',
'x-show' => "getStepIndex(step) <= {$loop->index}",
]),
size: \Filament\Support\Enums\IconSize::Large,
)
}}
@else
<span
x-show="getStepIndex(step) <= {{ $loop->index }}"
class="fi-sc-wizard-header-step-number"
>
{{ str_pad($loop->index + 1, 2, '0', STR_PAD_LEFT) }}
</span>
@endif
</div>
<div class="fi-sc-wizard-header-step-text">
@if (! $step->isLabelHidden())
<span class="fi-sc-wizard-header-step-label">
{{ $step->getLabel() }}
</span>
@endif
@if (filled($description = $step->getDescription()))
<span
class="fi-sc-wizard-header-step-description"
>
{{ $description }}
</span>
@endif
</div>
</button>
@if (! $loop->last)
<svg
fill="none"
preserveAspectRatio="none"
viewBox="0 0 22 80"
aria-hidden="true"
class="fi-sc-wizard-header-step-separator"
>
<path
d="M0 -2L20 40L0 82"
stroke-linejoin="round"
stroke="currentcolor"
vector-effect="non-scaling-stroke"
></path>
</svg>
@endif
</li>
@endforeach
</ol>
@endif
@foreach ($steps as $step)
{{ $step }}
@endforeach
<div x-cloak class="fi-sc-wizard-footer">
<div
x-cloak
@if (! $previousAction->isDisabled())
x-on:click="goToPreviousStep"
@endif
x-show="! isFirstStep()"
>
{{ $previousAction }}
</div>
<div x-show="isFirstStep()">
{{ $getCancelAction() }}
</div>
<div
x-cloak
@if (! $nextAction->isDisabled())
x-on:click="requestNextStep()"
@endif
x-bind:class="{ 'fi-hidden': isLastStep() }"
wire:loading.class="fi-disabled"
>
{{ $nextAction }}
</div>
<div x-bind:class="{ 'fi-hidden': ! isLastStep() }">
{{ $getSubmitAction() }}
</div>
</div>
</div>
@@ -0,0 +1,43 @@
@php
$id = $getId();
$key = $getKey();
$wizard = $getContainer()->getParentComponent();
$isContained = $wizard->isContained();
$alpineSubmitHandler = $hasFormWrapper() ? $wizard->getAlpineSubmitHandler() : null;
@endphp
<{{ filled($alpineSubmitHandler) ? 'form' : 'div' }}
x-bind:tabindex="$el.querySelector('[autofocus]') ? '-1' : '0'"
x-bind:class="{
'fi-active': step === @js($key),
}"
x-on:expand="
if (! isStepAccessible(@js($key))) {
return
}
step = @js($key)
"
@if (filled($alpineSubmitHandler))
x-on:submit.prevent="isLastStep() ? {!! $alpineSubmitHandler !!} : requestNextStep()"
@endif
x-cloak
x-ref="step-{{ $key }}"
{{
$attributes
->merge([
'aria-labelledby' => $id,
'id' => $id,
'role' => 'tabpanel',
], escape: false)
->merge($getExtraAttributes(), escape: false)
->class(['fi-sc-wizard-step'])
}}
>
{{ $getChildSchema() }}
@if (filled($alpineSubmitHandler))
{{-- This is a hack to allow the form to submit when the user presses the enter key, even if there is no other submit button in the form. --}}
<input type="submit" hidden />
@endif
</{{ filled($alpineSubmitHandler) ? 'form' : 'div' }}>