diff --git a/index.html b/index.html index 143557b..924934e 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,25 @@ - - - - - Vite + Vue + TS - - -
- - + + + + + + Vuetify Inline Fields + + + + + + + + + + +
+ + + diff --git a/src/App.vue b/src/App.vue index 60452b9..4c962e7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -17,7 +17,7 @@ - + @@ -26,22 +26,162 @@ - - diff --git a/src/components/docs/PropsComponent.vue b/src/components/docs/PropsComponent.vue deleted file mode 100644 index 62045d0..0000000 --- a/src/components/docs/PropsComponent.vue +++ /dev/null @@ -1,288 +0,0 @@ - - - - - diff --git a/src/components/docs/SassVariables.vue b/src/components/docs/SassVariables.vue deleted file mode 100644 index c4689c2..0000000 --- a/src/components/docs/SassVariables.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - diff --git a/src/components/docs/index.ts b/src/components/docs/index.ts deleted file mode 100644 index 0fe0ed9..0000000 --- a/src/components/docs/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import DependenciesComponent from '@/components/docs/DependenciesComponent.vue'; -import DescriptionComponent from '@/components/docs/DescriptionComponent.vue'; -import EventsComponent from '@/components/docs/EventsComponent.vue'; -import ExampleComponent from '@/components/docs/ExampleComponent.vue'; -import LegalComponent from '@/components/docs/LegalComponent.vue'; -import LicenseComponent from '@/components/docs/LicenseComponent.vue'; -import PropsComponent from '@/components/docs/PropsComponent.vue'; -import SassVariables from '@/components/docs/SassVariables.vue'; -import SlotsComponent from '@/components/docs/SlotsComponent.vue'; -import UsageComponent from '@/components/docs/UsageComponent.vue'; - -export { - DependenciesComponent, - DescriptionComponent, - EventsComponent, - ExampleComponent, - LegalComponent, - LicenseComponent, - PropsComponent, - SassVariables, - SlotsComponent, - UsageComponent, -}; diff --git a/src/components/DocsComponent.vue b/src/documentation/DocsPage.vue similarity index 80% rename from src/components/DocsComponent.vue rename to src/documentation/DocsPage.vue index 2cb4b15..0cf425b 100644 --- a/src/components/DocsComponent.vue +++ b/src/documentation/DocsPage.vue @@ -67,34 +67,37 @@ - + - + - + + + + - + - + - + - + - + - + - + @@ -102,17 +105,18 @@ import { inject, provide, reactive, ref } from 'vue'; import packageInfo from '../../package.json'; import { - DependenciesComponent, - DescriptionComponent, - EventsComponent, - ExampleComponent, - LegalComponent, - LicenseComponent, - PropsComponent, - SassVariables, - SlotsComponent, - UsageComponent, -} from '@/components/docs'; + ComponentsSection, + DependenciesSection, + DescriptionSection, + EventsSection, + ExampleSection, + LegalSection, + LicenseSection, + PropsSection, + SassVariablesSection, + SlotsSection, + UsageSection, +} from '@/documentation/sections'; const links = inject('links'); diff --git a/src/documentation/components/CheckboxComponent.vue b/src/documentation/components/CheckboxComponent.vue new file mode 100644 index 0000000..e296b1a --- /dev/null +++ b/src/documentation/components/CheckboxComponent.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/documentation/components/MenuComponent.vue b/src/documentation/components/MenuComponent.vue new file mode 100644 index 0000000..7eee755 --- /dev/null +++ b/src/documentation/components/MenuComponent.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/documentation/components/PropsTable.vue b/src/documentation/components/PropsTable.vue new file mode 100644 index 0000000..73e5f85 --- /dev/null +++ b/src/documentation/components/PropsTable.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/src/documentation/components/SelectComponent.vue b/src/documentation/components/SelectComponent.vue new file mode 100644 index 0000000..d9f22ce --- /dev/null +++ b/src/documentation/components/SelectComponent.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/documentation/components/SwitchComponent.vue b/src/documentation/components/SwitchComponent.vue new file mode 100644 index 0000000..058ce45 --- /dev/null +++ b/src/documentation/components/SwitchComponent.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/src/documentation/components/TextFieldComponent.vue b/src/documentation/components/TextFieldComponent.vue new file mode 100644 index 0000000..9925bff --- /dev/null +++ b/src/documentation/components/TextFieldComponent.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/documentation/components/TextareaComponent.vue b/src/documentation/components/TextareaComponent.vue new file mode 100644 index 0000000..4e191d4 --- /dev/null +++ b/src/documentation/components/TextareaComponent.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/documentation/components/index.js b/src/documentation/components/index.js new file mode 100644 index 0000000..b9dc699 --- /dev/null +++ b/src/documentation/components/index.js @@ -0,0 +1,15 @@ +import CheckboxComponent from './CheckboxComponent'; +import PropsTable from './PropsTable'; +import SelectComponent from './SelectComponent'; +import SwitchComponent from './SwitchComponent'; +import TextFieldComponent from './TextFieldComponent'; +import TextareaComponent from './TextareaComponent'; + +export { + CheckboxComponent, + PropsTable, + SelectComponent, + SwitchComponent, + TextFieldComponent, + TextareaComponent, +}; diff --git a/src/layout/AppBar.vue b/src/documentation/layout/AppBar.vue similarity index 58% rename from src/layout/AppBar.vue rename to src/documentation/layout/AppBar.vue index 62d309b..4c2f104 100644 --- a/src/layout/AppBar.vue +++ b/src/documentation/layout/AppBar.vue @@ -12,7 +12,6 @@ :width="iconSize.width" @click.stop="toggleDrawer" > - - - Github - - - - VCheckbox - - - - VSelect - - - - VSwitch - - - - VTextField - - - - - + + import { onMounted, ref } from 'vue'; import { useCoreStore } from '@/stores/index'; +import { useMenuStore } from '@/stores/menu'; import { useTheme } from 'vuetify'; const emit = defineEmits(['changedTheme', 'updatedDrawer']); @@ -166,6 +109,11 @@ defineProps({ }, }); +onMounted(() => { + getTheme(); +}); + +const menuStore = useMenuStore(); const store = useCoreStore(); const theme = useTheme(); @@ -173,15 +121,13 @@ const links = store.links; const themeName = ref('dark'); const drawer = ref(true); +const menuItems = [...menuStore.vuetifyLinks, ...menuStore.componentItems]; + const iconSize = ref({ height: 32, width: 32, }); -onMounted(() => { - getTheme(); -}); - function getTheme() { themeName.value = store.getTheme(); if (!themeName.value) { diff --git a/src/documentation/sections/ComponentsSection.vue b/src/documentation/sections/ComponentsSection.vue new file mode 100644 index 0000000..fdb6dd0 --- /dev/null +++ b/src/documentation/sections/ComponentsSection.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/components/docs/DependenciesComponent.vue b/src/documentation/sections/DependenciesSection.vue similarity index 78% rename from src/components/docs/DependenciesComponent.vue rename to src/documentation/sections/DependenciesSection.vue index e449f8d..0dd5049 100644 --- a/src/components/docs/DependenciesComponent.vue +++ b/src/documentation/sections/DependenciesSection.vue @@ -18,12 +18,23 @@ Vuetify v3 + > + Vuetify v3 +
Vue 3 + > + Vue 3 + +
+ + VueUse + @@ -34,7 +45,7 @@ import { inject } from 'vue'; import { useCoreStore } from '@/stores/index'; -const classes = inject('classes'); +const classes = inject('classes'); const store = useCoreStore(); diff --git a/src/components/docs/DescriptionComponent.vue b/src/documentation/sections/DescriptionSection.vue similarity index 99% rename from src/components/docs/DescriptionComponent.vue rename to src/documentation/sections/DescriptionSection.vue index 13638dd..f89462f 100644 --- a/src/components/docs/DescriptionComponent.vue +++ b/src/documentation/sections/DescriptionSection.vue @@ -25,6 +25,7 @@ diff --git a/src/components/docs/EventsComponent.vue b/src/documentation/sections/EventsSection.vue similarity index 73% rename from src/components/docs/EventsComponent.vue rename to src/documentation/sections/EventsSection.vue index 530647d..2ac5d4b 100644 --- a/src/components/docs/EventsComponent.vue +++ b/src/documentation/sections/EventsSection.vue @@ -13,6 +13,13 @@ Events + For component specific events, please refer to the Vuetify documentation. + + + @@ -65,8 +72,11 @@ diff --git a/src/components/docs/LegalComponent.vue b/src/documentation/sections/LegalSection.vue similarity index 99% rename from src/components/docs/LegalComponent.vue rename to src/documentation/sections/LegalSection.vue index 120dba2..a650a2b 100644 --- a/src/components/docs/LegalComponent.vue +++ b/src/documentation/sections/LegalSection.vue @@ -28,5 +28,6 @@ diff --git a/src/components/docs/LicenseComponent.vue b/src/documentation/sections/LicenseSection.vue similarity index 99% rename from src/components/docs/LicenseComponent.vue rename to src/documentation/sections/LicenseSection.vue index 41eb192..a77652a 100644 --- a/src/components/docs/LicenseComponent.vue +++ b/src/documentation/sections/LicenseSection.vue @@ -38,6 +38,7 @@ import { inject } from 'vue'; import { useCoreStore } from '@/stores/index'; + const classes = inject('classes'); const store = useCoreStore(); diff --git a/src/documentation/sections/PropsSection.vue b/src/documentation/sections/PropsSection.vue new file mode 100644 index 0000000..c9208d4 --- /dev/null +++ b/src/documentation/sections/PropsSection.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/documentation/sections/SassVariablesSection.vue b/src/documentation/sections/SassVariablesSection.vue new file mode 100644 index 0000000..b6c1e89 --- /dev/null +++ b/src/documentation/sections/SassVariablesSection.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/components/docs/SlotsComponent.vue b/src/documentation/sections/SlotsSection.vue similarity index 99% rename from src/components/docs/SlotsComponent.vue rename to src/documentation/sections/SlotsSection.vue index f087153..d6d55d2 100644 --- a/src/components/docs/SlotsComponent.vue +++ b/src/documentation/sections/SlotsSection.vue @@ -53,6 +53,7 @@ diff --git a/src/documentation/sections/index.js b/src/documentation/sections/index.js new file mode 100644 index 0000000..3409fd7 --- /dev/null +++ b/src/documentation/sections/index.js @@ -0,0 +1,25 @@ +import ComponentsSection from './ComponentsSection.vue'; +import DependenciesSection from './DependenciesSection.vue'; +import DescriptionSection from './DescriptionSection.vue'; +import EventsSection from './EventsSection.vue'; +import ExampleSection from './ExampleSection.vue'; +import LegalSection from './LegalSection.vue'; +import LicenseSection from './LicenseSection.vue'; +import PropsSection from './PropsSection.vue'; +import SassVariablesSection from './SassVariablesSection.vue'; +import SlotsSection from './SlotsSection.vue'; +import UsageSection from './UsageSection.vue'; + +export { + ComponentsSection, + DependenciesSection, + DescriptionSection, + EventsSection, + ExampleSection, + LegalSection, + LicenseSection, + PropsSection, + SassVariablesSection, + SlotsSection, + UsageSection, +}; diff --git a/src/main.ts b/src/main.ts index 1161d8c..cae2842 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,14 @@ import { createApp } from 'vue'; import { createPinia } from 'pinia'; import { registerPlugins } from './plugins'; import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; +import { + VInlineCheckbox, + VInlineSelect, + VInlineSwitch, + VInlineTextField, + VInlineTextarea, +} from './index'; + const app = createApp(App); app.use(CodeBlock); @@ -12,6 +20,12 @@ app.use(createPinia()); app.component('font-awesome-icon', FontAwesomeIcon); app.component('FaIcon', FontAwesomeIcon); +app.component('VInlineCheckbox', VInlineCheckbox); +app.component('VInlineSelect', VInlineSelect); +app.component('VInlineSwitch', VInlineSwitch); +app.component('VInlineTextField', VInlineTextField); +app.component('VInlineTextarea', VInlineTextarea); + registerPlugins(app); app.mount('#app'); diff --git a/src/playground/configs/PlaygroundApp.vue b/src/playground/configs/PlaygroundApp.vue index 71d9313..6c643d1 100644 --- a/src/playground/configs/PlaygroundApp.vue +++ b/src/playground/configs/PlaygroundApp.vue @@ -34,7 +34,7 @@ import { provide } from 'vue'; import { useCoreStore } from '@/stores/index'; import PlaygroundPage from '@/playground/PlaygroundPage.vue'; -import AppBar from '@/layout/AppBar.vue'; +import AppBar from '@/documentation/layout/AppBar.vue'; const store = useCoreStore(); provide('links', store.links); diff --git a/src/playground/configs/PlaygroundPage.template.vue b/src/playground/configs/PlaygroundPage.template.vue index 1e1b96f..d55fc1a 100644 --- a/src/playground/configs/PlaygroundPage.template.vue +++ b/src/playground/configs/PlaygroundPage.template.vue @@ -21,6 +21,7 @@ :cancel-icon-text="componentOptions.cancelIconText" :close-siblings="componentOptions.closeSiblings" :color="componentOptions.color" + :density="componentOptions.density" :disabled="componentOptions.disabled" :do-not-save="componentOptions.doNotSave" :field-only="componentOptions.fieldOnly" @@ -51,6 +52,7 @@ :cancel-icon-text="componentOptions.cancelIconText" :close-siblings="componentOptions.closeSiblings" :color="componentOptions.color" + :density="componentOptions.density" :disabled="componentOptions.disabled" :do-not-save="componentOptions.doNotSave" :empty-text="componentOptions.emptyText" @@ -72,6 +74,7 @@ :underline-style="componentOptions.underlineStyle" :underline-width="componentOptions.underlineWidth" :underlined="componentOptions.underlined" + :variant="componentOptions.variant" @error="showError = $event" @loading="loading = $event" @update="updatedValue($event, 'select')" @@ -89,6 +92,7 @@ :cancel-icon-text="componentOptions.cancelIconText" :close-siblings="componentOptions.closeSiblings" :color="componentOptions.color" + :density="componentOptions.density" :disabled="componentOptions.disabled" :do-not-save="componentOptions.doNotSave" :field-only="componentOptions.fieldOnly" @@ -105,6 +109,7 @@ :underline-style="componentOptions.underlineStyle" :underline-width="componentOptions.underlineWidth" :underlined="componentOptions.underlined" + :variant="componentOptions.variant" @error="showError = $event" @loading="loading = $event" @update="updatedValue($event, 'text-field')" @@ -121,6 +126,7 @@ :cancel-icon-text="componentOptions.cancelIconText" :close-siblings="componentOptions.closeSiblings" :color="componentOptions.color" + :density="componentOptions.density" :disabled="componentOptions.disabled" :do-not-save="componentOptions.doNotSave" :field-only="componentOptions.fieldOnly" @@ -137,6 +143,7 @@ :underline-style="componentOptions.underlineStyle" :underline-width="componentOptions.underlineWidth" :underlined="componentOptions.underlined" + :variant="componentOptions.variant" @error="showError = $event" @loading="loading = $event" @update="updatedValue($event, 'textarea')" @@ -154,6 +161,7 @@ :cancel-icon-text="componentOptions.cancelIconText" :close-siblings="componentOptions.closeSiblings" :color="componentOptions.color" + :density="componentOptions.density" :disabled="componentOptions.disabled" :do-not-save="componentOptions.doNotSave" :field-only="componentOptions.fieldOnly" @@ -209,6 +217,7 @@ const componentOptions = reactive({ cancelIconText: 'Cancel', closeSiblings: true, color: 'primary', + density: 'compact', disabled: false, doNotSave: false, emptyText: 'empty', @@ -236,6 +245,7 @@ const componentOptions = reactive({ underlineStyle: 'dotted', underlineWidth: '1px', underlined: true, + variant: 'underlined', }); const headers = [ @@ -249,7 +259,7 @@ const headers = [ align: 'start', key: 'active', title: 'Active', - width: 100, + width: 125, }, { align: 'start', diff --git a/src/plugin/VInlineCheckbox.vue b/src/plugin/VInlineCheckbox.vue index dabb4be..2c40bee 100644 --- a/src/plugin/VInlineCheckbox.vue +++ b/src/plugin/VInlineCheckbox.vue @@ -1,89 +1,95 @@ @@ -102,10 +108,13 @@ import { useToggleField, } from './composables/methods'; import { - useFieldContainerClass, useDisplayContainerClass, + useDisplaySelectionControlClasses, + useDisplayValueClass, + useFieldContainerClass, + useInlineFieldsContainerClass, } from './composables/classes'; -import { useFieldDisplayStyles } from './composables/styles'; +import { useDisplayValueStyles } from './composables/styles'; import inlineEmits from './utils/emits'; @@ -130,8 +139,27 @@ const displayValue = computed(() => { // ------------------------------------------------ Class & Styles // -const fieldContainerClass = computed(() => useFieldContainerClass('checkbox', showField.value)); -const fieldDisplayClass = computed(() => useDisplayContainerClass( +const inlineFieldsContainerClass = computed(() => useInlineFieldsContainerClass({ + density: settings.density, + field: 'v-checkbox', + tableField: settings.tableField, +})); + +const displayContainerClass = computed(() => useDisplayContainerClass({ + density: settings.density, + field: 'v-checkbox', +})); + +const displaySelectionControlClasses = useDisplaySelectionControlClasses({ + density: settings.density, +}); + +const fieldContainerClass = computed(() => useFieldContainerClass({ + active: showField.value, + name: 'checkbox', +})); + +const displayValueClass = computed(() => useDisplayValueClass( 'checkbox', settings.valueColor, { @@ -139,7 +167,8 @@ const fieldDisplayClass = computed(() => useDisplayContainerClass( error, } )); -const fieldDisplayStyle = computed(() => useFieldDisplayStyles({ + +const displayValueStyle = computed(() => useDisplayValueStyles({ color: settings.color, error, underlineColor: settings.underlineColor, diff --git a/src/plugin/VInlineSelect.vue b/src/plugin/VInlineSelect.vue index 5b76aa6..ef11345 100644 --- a/src/plugin/VInlineSelect.vue +++ b/src/plugin/VInlineSelect.vue @@ -1,83 +1,88 @@ @@ -98,10 +103,13 @@ import { useToggleField, } from './composables/methods'; import { - useFieldContainerClass, useDisplayContainerClass, + useDisplayInputControlClasses, + useDisplayValueClass, + useFieldContainerClass, + useInlineFieldsContainerClass, } from './composables/classes'; -import { useFieldDisplayStyles } from './composables/styles'; +import { useDisplayValueStyles } from './composables/styles'; import inlineEmits from './utils/emits'; @@ -143,8 +151,28 @@ watchEffect(() => { // ------------------------------------------------ Class & Styles // -const fieldContainerClass = computed(() => useFieldContainerClass('select', showField.value)); -const fieldDisplayClass = computed(() => useDisplayContainerClass( +const inlineFieldsContainerClass = computed(() => useInlineFieldsContainerClass({ + density: settings.density, + field: 'v-select', + tableField: settings.tableField, +})); + +const displayContainerClass = computed(() => useDisplayContainerClass({ + density: settings.density, + field: 'v-select', +})); + +const displayInputControlClasses = useDisplayInputControlClasses({ + density: settings.density, + variant: settings.variant, +}); + +const fieldContainerClass = computed(() => useFieldContainerClass({ + active: showField.value, + name: 'select', +})); + +const displayValueClass = computed(() => useDisplayValueClass( 'select', settings.valueColor, { @@ -153,7 +181,8 @@ const fieldDisplayClass = computed(() => useDisplayContainerClass( error, } )); -const fieldDisplayStyle = computed(() => useFieldDisplayStyles({ + +const displayValueStyle = computed(() => useDisplayValueStyles({ color: settings.color, error, underlineColor: settings.underlineColor, diff --git a/src/plugin/VInlineSwitch.vue b/src/plugin/VInlineSwitch.vue index fb7ac68..33edf75 100644 --- a/src/plugin/VInlineSwitch.vue +++ b/src/plugin/VInlineSwitch.vue @@ -1,90 +1,95 @@ @@ -103,10 +108,13 @@ import { useToggleField, } from './composables/methods'; import { - useFieldContainerClass, useDisplayContainerClass, + useDisplaySelectionControlClasses, + useDisplayValueClass, + useFieldContainerClass, + useInlineFieldsContainerClass, } from './composables/classes'; -import { useFieldDisplayStyles } from './composables/styles'; +import { useDisplayValueStyles } from './composables/styles'; import inlineEmits from './utils/emits'; @@ -131,8 +139,27 @@ const displayValue = computed(() => { // ------------------------------------------------ Class & Styles // -const fieldContainerClass = computed(() => useFieldContainerClass('switch', showField.value)); -const fieldDisplayClass = computed(() => useDisplayContainerClass( +const inlineFieldsContainerClass = computed(() => useInlineFieldsContainerClass({ + density: settings.density, + field: 'v-switch', + tableField: settings.tableField, +})); + +const displayContainerClass = computed(() => useDisplayContainerClass({ + density: settings.density, + field: 'v-switch', +})); + +const displaySelectionControlClasses = useDisplaySelectionControlClasses({ + density: settings.density, +}); + +const fieldContainerClass = computed(() => useFieldContainerClass({ + active: showField.value, + name: 'switch', +})); + +const displayValueClass = computed(() => useDisplayValueClass( 'switch', settings.valueColor, { @@ -140,7 +167,8 @@ const fieldDisplayClass = computed(() => useDisplayContainerClass( error, } )); -const fieldDisplayStyle = computed(() => useFieldDisplayStyles({ + +const displayValueStyle = computed(() => useDisplayValueStyles({ color: settings.color, error, underlineColor: settings.underlineColor, diff --git a/src/plugin/VInlineTextField.vue b/src/plugin/VInlineTextField.vue index d79594a..b68583c 100644 --- a/src/plugin/VInlineTextField.vue +++ b/src/plugin/VInlineTextField.vue @@ -1,80 +1,87 @@ @@ -95,10 +102,13 @@ import { useTruncateText, } from './composables/methods'; import { - useFieldContainerClass, useDisplayContainerClass, + useDisplayInputControlClasses, + useDisplayValueClass, + useFieldContainerClass, + useInlineFieldsContainerClass, } from './composables/classes'; -import { useFieldDisplayStyles } from './composables/styles'; +import { useDisplayValueStyles } from './composables/styles'; import inlineEmits from './utils/emits'; @@ -140,8 +150,28 @@ const displayValue = computed(() => { // ------------------------------------------------ Class & Styles // -const fieldContainerClass = computed(() => useFieldContainerClass('text-field', showField.value)); -const fieldDisplayClass = computed(() => useDisplayContainerClass( +const inlineFieldsContainerClass = computed(() => useInlineFieldsContainerClass({ + density: settings.density, + field: 'v-text-field', + tableField: settings.tableField, +})); + +const displayContainerClass = computed(() => useDisplayContainerClass({ + density: settings.density, + field: 'v-text-field', +})); + +const displayInputControlClasses = useDisplayInputControlClasses({ + density: settings.density, + variant: settings.variant, +}); + +const fieldContainerClass = computed(() => useFieldContainerClass({ + active: showField.value, + name: 'text-field', +})); + +const displayValueClass = computed(() => useDisplayValueClass( 'text-field', settings.valueColor, { @@ -150,7 +180,8 @@ const fieldDisplayClass = computed(() => useDisplayContainerClass( error, } )); -const fieldDisplayStyle = computed(() => useFieldDisplayStyles({ + +const displayValueStyle = computed(() => useDisplayValueStyles({ color: settings.color, error, underlineColor: settings.underlineColor, diff --git a/src/plugin/VInlineTextarea.vue b/src/plugin/VInlineTextarea.vue index 1a2805a..c466e5f 100644 --- a/src/plugin/VInlineTextarea.vue +++ b/src/plugin/VInlineTextarea.vue @@ -1,79 +1,86 @@ @@ -94,10 +101,13 @@ import { useTruncateText, } from './composables/methods'; import { - useFieldContainerClass, useDisplayContainerClass, + useDisplayInputControlClasses, + useDisplayValueClass, + useFieldContainerClass, + useInlineFieldsContainerClass, } from './composables/classes'; -import { useFieldDisplayStyles } from './composables/styles'; +import { useDisplayValueStyles } from './composables/styles'; import inlineEmits from './utils/emits'; @@ -139,8 +149,28 @@ const displayValue = computed(() => { // ------------------------------------------------ Class & Styles // -const fieldContainerClass = computed(() => useFieldContainerClass('textarea', showField.value)); -const fieldDisplayClass = computed(() => useDisplayContainerClass( +const inlineFieldsContainerClass = computed(() => useInlineFieldsContainerClass({ + density: settings.density, + field: 'v-textarea', + tableField: settings.tableField, +})); + +const displayContainerClass = computed(() => useDisplayContainerClass({ + density: settings.density, + field: 'v-textarea', +})); + +const displayInputControlClasses = useDisplayInputControlClasses({ + density: settings.density, + variant: settings.variant, +}); + +const fieldContainerClass = computed(() => useFieldContainerClass({ + active: showField.value, + name: 'textarea', +})); + +const displayValueClass = computed(() => useDisplayValueClass( 'textarea', settings.valueColor, { @@ -149,7 +179,8 @@ const fieldDisplayClass = computed(() => useDisplayContainerClass( error, } )); -const fieldDisplayStyle = computed(() => useFieldDisplayStyles({ + +const displayValueStyle = computed(() => useDisplayValueStyles({ color: settings.color, error, underlineColor: settings.underlineColor, diff --git a/src/plugin/components/BooleanIcons.vue b/src/plugin/components/BooleanIcons.vue index 1fd16d7..8da2be1 100644 --- a/src/plugin/components/BooleanIcons.vue +++ b/src/plugin/components/BooleanIcons.vue @@ -1,16 +1,18 @@ diff --git a/src/plugin/composables/classes.ts b/src/plugin/composables/classes.ts index 9484b43..b482c04 100644 --- a/src/plugin/composables/classes.ts +++ b/src/plugin/composables/classes.ts @@ -1,7 +1,64 @@ -import { UseDisplayContainerClass } from '@/types'; +import { + UseDisplayContainerClass, + UseDisplayInputControlClass, + UseDisplaySelectionControlClass, + UseDisplayValueClass, + UseFieldContainerClass, + UseInlineFieldsContainerClass, +} from '@/types'; import { componentName } from '../utils/globals'; -export const useDisplayContainerClass: UseDisplayContainerClass = (name, valueColor, options) => { + +// ------------------------------------------------ Main Container // +export const useInlineFieldsContainerClass: UseInlineFieldsContainerClass = (options) => { + const { field = '', density = '', tableField = false } = options; + + return { + [`${componentName}--container`]: true, + [`${componentName}--container-inline-${field}`]: true, + [`${componentName}--container-inline-${field}-${density}`]: true, + [`${componentName}--container-inline-table-centered`]: tableField, + }; +}; + + +// ------------------------------------------------ Display Value Container // +export const useDisplayContainerClass: UseDisplayContainerClass = (options) => { + const { field = '', density = '' } = options; + + return { + [`${componentName}`]: true, + [`${componentName}--container-display-container`]: true, + [`${field}`]: true, + 'v-input': true, + [`v-input--density-${density}`]: true, + 'v-input--horizontal': true, + }; +}; + +export const useDisplayInputControlClasses: UseDisplayInputControlClass = (options) => { + const { density = '', variant = '' } = options; + + return { + 'v-input': true, + 'v-input--dirty': true, + 'v-input--horizontal': true, + 'v-text-field': true, + [`v-input--density-${density}`]: true, + [`v-text-field--plain-${variant}`]: true, + }; +}; + +export const useDisplaySelectionControlClasses: UseDisplaySelectionControlClass = (options) => { + const { density = '' } = options; + + return { + 'v-selection-control': true, + [`v-selection-control--density-${density}`]: true, + }; +}; + +export const useDisplayValueClass: UseDisplayValueClass = (name, valueColor, options) => { const { disabled = false, error = false, empty = false } = options; return { @@ -15,7 +72,11 @@ export const useDisplayContainerClass: UseDisplayContainerClass = (name, valueCo }; }; -export const useFieldContainerClass = (name: string, active = false): object => { + +// ------------------------------------------------ Field Container // +export const useFieldContainerClass: UseFieldContainerClass = (options): object => { + const { name, active = false } = options; + return { [`${componentName}`]: true, [`${componentName}--field-value-${name}`]: true, diff --git a/src/plugin/composables/styles.ts b/src/plugin/composables/styles.ts index 0226174..2e04f2b 100644 --- a/src/plugin/composables/styles.ts +++ b/src/plugin/composables/styles.ts @@ -1,8 +1,8 @@ import { CSSProperties } from 'vue'; -import { UseFieldDisplayStyles } from '@/types'; +import { UseDisplayValueStyles } from '@/types'; // -------------------------------------------------- Value Styles // -export const useFieldDisplayStyles: UseFieldDisplayStyles = (options) => { +export const useDisplayValueStyles: UseDisplayValueStyles = (options) => { const { underlineStyle, underlineWidth, color, error, underlined } = options; let { underlineColor } = options; underlineColor = underlineColor || color; diff --git a/src/plugin/styles/main.scss b/src/plugin/styles/main.scss index db87cbd..d881a47 100644 --- a/src/plugin/styles/main.scss +++ b/src/plugin/styles/main.scss @@ -1,7 +1,121 @@ +:root { + --v-inline-fields-top-padding-compact: 13px; + --v-inline-fields-top-padding-comfortable: 17px; + --v-inline-fields-top-padding-default: 21px; +} + .v-inline-fields { + &--container { + &-inline { + + // tableField prop // + &-table-centered { + --v-inline-fields-top-padding-compact: 0; + --v-inline-fields-top-padding-comfortable: 0; + --v-inline-fields-top-padding-default: 0; + + .v-inline-fields--field-value-text-field { + .v-input--density-compact { + + // Variants - plain & underlined // + .v-field--variant-plain, + .v-field--variant-underlined { + .v-field__input { + min-height: unset !important; + padding-bottom: 0; + padding-top: 3px; + } + } + } + + .v-input--density-comfortable { + + // Variants - plain & underlined // + .v-field--variant-plain, + .v-field--variant-underlined { + .v-field__input { + min-height: unset !important; + padding-bottom: 0; + padding-top: 2px; + } + } + } + + .v-input--density-default { + + // Variants - plain & underlined // + .v-field--variant-plain, + .v-field--variant-underlined { + .v-field__input { + min-height: unset !important; + padding-bottom: 0; + padding-top: 1px; + } + } + } + } + } + + // Checkbox & Switch // + &-v-checkbox, + &-v-switch { + &-compact { + padding-top: var(--v-inline-fields-top-padding-compact); + } + + &-comfortable { + padding-top: var(--v-inline-fields-top-padding-comfortable); + } + + &-default { + padding-top: var(--v-inline-fields-top-padding-default); + } + + .v-selection-control { + padding-bottom: 1px; + } + } + + // Select & Textarea & Text Field // + &-v-select, + &-v-textarea, + &-v-text-field { + &-compact { + .v-inline-fields--container-display-container-fields { + padding-top: var(--v-inline-fields-top-padding-compact); + + > div { + line-height: 1.5rem; + } + } + } + + &-comfortable { + .v-inline-fields--container-display-container-fields { + padding-top: var(--v-inline-fields-top-padding-comfortable); + + > div { + padding-bottom: 0; + } + } + } + + &-default { + .v-inline-fields--container-display-container-fields { + padding-top: var(--v-inline-fields-top-padding-default); + + > div { + line-height: 1.5rem; + padding-bottom: 5px; + } + } + } + } + } + } + &--display { &-value { - border-bottom-width: 10px; cursor: pointer; &-empty { @@ -12,14 +126,24 @@ } &--field-value { - &-checkbox { + + // Checkbox & Switch // + &-checkbox, + &-switch { .v-input { + display: flex; + &__append { margin-left: 0; } } + + :deep(.v-input__control) { + display: inline-flex !important; + } } + // Select & Textarea & Text Field // &-select, &-textarea, &-text-field { @@ -41,4 +165,11 @@ &--save-fields-container { height: 100%; } + + &--boolean-icons { + font-size: calc(var(--v-icon-size-multiplier) * 1em); + font-weight: bold; + line-height: 1.5rem; + padding-bottom: 2px; + } } diff --git a/src/plugin/utils/emits.ts b/src/plugin/utils/emits.ts index 4b2da77..84669ab 100644 --- a/src/plugin/utils/emits.ts +++ b/src/plugin/utils/emits.ts @@ -1,7 +1,7 @@ export default [ - 'error', // ? emits boolean value - 'loading', // ? emits boolean value - 'update', // ? emits api response object - 'update:closeSiblingFields', // ? emits boolean value - 'update:model-value', // ? emits updated model value + 'error', // ? emits boolean value + 'loading', // ? emits boolean value + 'update', // ? emits api response object + 'update:closeSiblingFields', // ? emits boolean value + 'update:model-value', // ? emits updated model value ]; diff --git a/src/plugin/utils/props.ts b/src/plugin/utils/props.ts index ef3f0e0..02641b4 100644 --- a/src/plugin/utils/props.ts +++ b/src/plugin/utils/props.ts @@ -57,8 +57,11 @@ export const sharedProps = { // ? The column name of the field - [ All Fields ] // name: '', + // ? If the field is used in a table this will remove the top padding // + tableField: true, + // ? The color of the underline - [ All Fields ] // - underlineColor: '', + underlineColor: 'primary', // ? The style of the underline - [ All Fields ] // underlineStyle: 'dotted', @@ -210,6 +213,9 @@ const textareaProps = { // ? Automatically grow the textarea depending on amount of text // autoGrow: true, + // ? The height of the textarea when autoGrow is false // + rows: 1, + // ? The variant of the field // variant: 'underlined' as const, }, diff --git a/src/plugins/theme.ts b/src/plugins/theme.ts index 53bae22..de17815 100644 --- a/src/plugins/theme.ts +++ b/src/plugins/theme.ts @@ -2,6 +2,7 @@ import colors from 'vuetify/lib/util/colors.mjs'; export const dark = { colors: { + accent: '#d00274', danger: colors.red.base, error: colors.red.base, info: colors.teal.base, @@ -15,6 +16,7 @@ export const dark = { export const light = { colors: { + accent: '#905', danger: colors.red.base, error: colors.red.base, info: colors.teal.darken1, diff --git a/src/stores/index.ts b/src/stores/index.ts index 6f2d03a..4293990 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,63 +1,60 @@ import { defineStore } from 'pinia'; import packageJson from '@root/package.json'; -const packageName = packageJson.name; - - -// Links // -const repoBaseUrl = `https://github.com/webdevnerdstuff/${packageName}`; -const links = { - changeLog: `${repoBaseUrl}/blob/main/CHANGELOG.md`, - github: repoBaseUrl, - githubProfile: 'https://github.com/webdevnerdstuff', - license: `${repoBaseUrl}/blob/main/LICENSE.md`, - npm: `https://www.npmjs.com/package/${packageName}`, - vue: 'https://vuejs.org/', - vuetify: 'https://vuetifyjs.com/', - vuetifyGithub: 'https://github.com/vuetifyjs/vuetify', -}; - -interface State { - links: object; - package: object; - pluginVersion: string | number; - storageName: string; -} - -export const useCoreStore = defineStore('core', { - actions: { + +export const useCoreStore = defineStore('core', () => { + const packageName = packageJson.name; + const storageName = 'vuetify-inline-fields'; + + // Links // + const repoBaseUrl = `https://github.com/webdevnerdstuff/${packageName}`; + const links = { + changeLog: `${repoBaseUrl}/blob/main/CHANGELOG.md`, + github: repoBaseUrl, + githubProfile: 'https://github.com/webdevnerdstuff', + license: `${repoBaseUrl}/blob/main/LICENSE.md`, + npm: `https://www.npmjs.com/package/${packageName}`, + vue: 'https://vuejs.org/', + vueUse: 'https://vueuse.org/', + vuetify: 'https://vuetifyjs.com/', + vuetifyGithub: 'https://github.com/vuetifyjs/vuetify', + }; + + const actions = { setLocalStorage(val: string): string { - const oldValue = localStorage.getItem(this.storageName); + const oldValue = localStorage.getItem(storageName); const newValue = val ?? oldValue; - localStorage.setItem(this.storageName, newValue); + localStorage.setItem(storageName, newValue); return newValue; }, setTheme(val: string): string { const themeName = val === 'dark' ? 'light' : 'dark'; - const currentTheme = localStorage.getItem(`${this.storageName}-theme`); + const currentTheme = localStorage.getItem(`${storageName}-theme`); const newTheme = themeName ?? currentTheme; - localStorage.setItem(`${this.storageName}-theme`, newTheme); + localStorage.setItem(`${storageName}-theme`, newTheme); return newTheme; }, - }, - getters: { - getLocalStorage: (state: State) => (): unknown => { - const value = localStorage.getItem(state.storageName); + }; + + const getters = { + getLocalStorage: () => (): unknown => { + const value = localStorage.getItem(storageName); return value; }, - getTheme: (state: State) => (): unknown => { - const value = localStorage.getItem(`${state.storageName}-theme`); + getTheme: () => { + const value = localStorage.getItem(`${storageName}-theme`); return value; }, - }, - state: (): State => { - return { - links, - package: packageJson, - pluginVersion: packageJson.version, - storageName: 'vuetify-inline-fields', - }; - }, + }; + + return { + ...actions, + ...getters, + links, + package: packageJson, + pluginVersion: packageJson.version, + storageName, + }; }); diff --git a/src/stores/menu.ts b/src/stores/menu.ts new file mode 100644 index 0000000..cbf0d72 --- /dev/null +++ b/src/stores/menu.ts @@ -0,0 +1,163 @@ +import { defineStore } from 'pinia'; +import { useCoreStore } from './index'; + + +export const useMenuStore = defineStore('menu', () => { + const coreStore = useCoreStore(); + const links = coreStore.links; + + const componentItems = [ + { + href: '#components-v-inline-checkbox', + icon: 'mdi:mdi-checkbox-outline', + key: 'v-inline-checkbox', + link: `${links.vuetify}en/api/v-checkbox/`, + title: 'VInlineCheckbox', + topTitle: 'VCheckbox', + + }, + { + href: '#components-v-inline-select', + icon: 'mdi:mdi-format-list-bulleted', + key: 'v-inline-select', + link: `${links.vuetify}en/api/v-select/`, + title: 'VInlineSelect', + topTitle: 'VSelect', + }, + { + href: '#components-v-inline-switch', + icon: 'mdi:mdi-toggle-switch-off-outline', + key: 'v-inline-switch', + link: `${links.vuetify}en/api/v-switch/`, + title: 'VInlineSwitch', + topTitle: 'VSwitch', + }, + { + href: '#components-v-inline-textarea', + icon: 'mdi:mdi-text-long', + key: 'v-inline-textarea', + link: `${links.vuetify}en/api/v-textarea/`, + title: 'VInlineTextarea', + topTitle: 'VTextarea', + }, + { + href: '#components-v-inline-text-field', + icon: 'mdi:mdi-minus', + key: 'v-inline-text-field', + link: `${links.vuetify}en/api/v-text-field/`, + title: 'VInlineTextField', + topTitle: 'VTextField', + }, + ]; + + const vuetifyLinks = [ + { + icon: 'mdi:mdi-github', + key: 'vuetify-github', + link: links.vuetifyGithub, + title: 'Github', + }, + { + key: 'vuetify', + link: `${links.vuetify}en/components/all/`, + title: 'Vuetify Components', + }, + ]; + + const menuItems = [ + { + href: '#home', + icon: 'mdi:mdi-home', + title: 'Home', + }, + { + href: '#installation', + icon: 'mdi:mdi-plus-thick', + title: 'Installation', + }, + { + href: '#description', + icon: 'mdi:mdi-information-outline', + title: 'Description', + }, + { + href: '#props', + icon: 'mdi:mdi-cog', + items: [ + { + href: '#props', + icon: 'mdi:mdi-cog', + key: 'shared-props', + title: 'Props', + }, + { + href: '#props-shared', + icon: 'mdi:mdi-share-all', + key: 'shared-props', + title: 'Shared', + }, + { + href: '#props-save-and-loading-icon', + icon: 'mdi:mdi-content-save', + key: 'props-save-and-loading-icon', + title: 'Save & Loading', + }, + { + href: '#props-true-false-icon', + icon: 'mdi:mdi-content-save', + key: 'props-true-false-icon', + title: 'True/False Icons', + }, + ], + title: 'Props', + }, + { + href: '#components', + icon: 'mdi:mdi-cog', + items: componentItems, + key: 'components', + title: 'Components', + }, + { + href: '#events', + icon: 'mdi:mdi-calendar-star', + title: 'Events', + }, + { + href: '#slots', + icon: 'mdi:mdi-slot-machine', + title: 'Slots', + }, + { + href: '#sass-variables', + icon: 'mdi:mdi-sass', + title: 'SASS Variables', + }, + { + href: '#example', + icon: 'mdi:mdi-code-json', + title: 'Example', + }, + { + href: '#dependencies', + icon: 'mdi:mdi-asterisk-circle-outline', + title: 'Dependencies', + }, + { + href: '#license', + icon: 'mdi:mdi-card-account-details-outline', + title: 'License', + }, + { + href: '#legal', + icon: 'mdi:mdi-scale-balance', + title: 'Legal', + }, + ]; + + return { + componentItems, + menuItems, + vuetifyLinks, + }; +}); diff --git a/src/stores/props.ts b/src/stores/props.ts new file mode 100644 index 0000000..226a4b0 --- /dev/null +++ b/src/stores/props.ts @@ -0,0 +1,524 @@ +import { defineStore } from 'pinia'; + + +const propsSupported = { + headers: [ + { + align: 'start', + filterable: true, + key: 'name', + sortable: true, + title: 'Name', + width: '15%', + }, + { + align: 'start', + filterable: false, + key: 'type', + sortable: false, + title: 'Type', + width: '20%', + }, + { + align: 'start', + filterable: false, + key: 'default', + sortable: false, + title: 'Default', + }, + { + align: 'start', + filterable: false, + key: 'desc', + sortable: false, + title: 'Description', + }, + ], + items: [ + { + default: 'TBD', + desc: 'TBD', + name: 'TBD', + type: 'TBD', + }, + ], +}; + +const colorDesc = 'Applies specified color to the'; +const densityDesc = 'Adjusts the vertical height used by the component'; +const variantDesc = 'Applies a distinct style to the'; + +const sharedProps = [ + { + default: 'undefined', + desc: 'The api route to save the field if the doNotSave prop is set to false', + name: 'apiRoute', + type: 'string | undefined', + }, + { + default: 'default', + desc: `${colorDesc} cancel button`, + name: 'cancelButtonColor', + type: "VBtn['$props']['color']", + }, + { + default: 'x-small', + desc: 'Sets the height and width of the cancel button', + name: 'cancelButtonSize', + type: "VBtn['$props']['size']", + }, + { + default: 'Cancel', + desc: 'The title of the cancel button', + name: 'cancelButtonTitle', + type: 'string | undefined', + }, + { + default: 'tonal', + desc: `${variantDesc} cancel button`, + name: 'cancelButtonVariant', + type: "VBtn['$props']['variant']", + }, + { + default: 'mdi:mdi-close', + desc: 'The icon to use to cancel', + name: 'cancelIcon', + type: 'string', + }, + { + default: 'default', + desc: `${colorDesc} cancel icon`, + name: 'cancelIconColor', + type: 'string', + }, + { + default: false, + desc: 'If true, the field will close when the user opens another inline form element', + name: 'closeSiblings', + type: 'boolean', + }, + { + default: 'primary', + desc: `${colorDesc} control`, + name: 'color', + type: 'string', + }, + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: 'string', + }, + { + default: false, + desc: 'Disables the field', + name: 'disabled', + type: 'boolean', + }, + { + default: true, + desc: 'If true the component will not use axios to attempt to save the value. The prop apiRoute is required if this prop is set to false', + name: 'doNotSave', + type: 'boolean', + }, + { + default: 'empty', + desc: 'Text to display when the field is empty', + name: 'emptyText', + type: 'string', + }, + { + default: false, + desc: 'If set to true will only show the field', + name: 'fieldOnly', + type: 'boolean', + }, + { + default: true, + desc: 'Hides hint and validation errors. When set to auto messages will be rendered only if there\'s a message (hint, error message, counter value etc) to display', + name: 'hideDetails', + type: 'boolean' + }, + { + default: () => ({}), + desc: 'The item object', + name: 'item', + type: 'Record', + }, + { + default: 'undefined', + desc: 'Sets the text of the v-label or v-field-label component', + name: 'label', + type: 'string', + }, + { + default: 'PUT', + desc: 'The http method to use when saving the text field', + name: 'method', + type: 'string', + }, + { + default: 'undefined', + desc: "Sets the component's name attribute", + name: 'name', + type: 'string', + }, + { + default: true, + desc: 'Adjusts padding to help the field to be vertically centered in the table cell', + name: 'tableField', + type: 'boolean', + }, + { + default: 'primary', + desc: `${colorDesc} display value underline`, + name: 'underlineColor', + type: 'string', + }, + { + default: 'dotted', + desc: 'The style of the display value underline', + name: 'underlineStyle', + type: 'string', + }, + { + default: '1px', + desc: 'The width of the display value underline', + name: 'underlineWidth', + type: 'string', + }, + { + default: true, + desc: 'Displays/Hides the display value underline', + name: 'underlined', + type: 'boolean', + }, + { + default: 'default', + desc: `${colorDesc} value`, + name: 'valueColor', + type: 'string', + }, +]; + +const autofocusProp = [ + { + default: false, + desc: 'If true, the field will autofocus', + name: 'autofocus', + type: 'boolean', + }, +]; + +const saveAndLoadingIconProps = [ + { + default: false, + desc: 'Displays/Hides the save icon', + name: 'hideSaveIcon', + type: 'boolean', + }, + { + default: 'mdi:mdi-loading mdi:mdi-spin', + desc: 'The icon to use when loading', + name: 'loadingIcon', + type: 'string', + }, + { + default: 'primary', + desc: `${colorDesc} loading icon`, + name: 'loadingIconColor', + type: 'string', + }, + { + default: 'primary', + desc: `${colorDesc} save button`, + name: 'saveButtonColor', + type: "VBtn['$props']['color']", + }, + { + default: 'x-small', + desc: 'Sets the height and width of the save button', + name: 'saveButtonSize', + type: "VBtn['$props']['size']", + }, + { + default: 'Save', + desc: 'The title of the save button', + name: 'saveButtonTitle', + type: 'string | undefined', + }, + { + default: 'text', + desc: `${variantDesc} save button`, + name: 'saveButtonVariant', + type: "VBtn['$props']['variant']", + }, + { + default: 'mdi:mdi-content-save', + desc: 'The icon to use to save', + name: 'saveIcon', + type: 'string', + }, + { + default: 'primary', + desc: `${colorDesc} save icon`, + name: 'saveIconColor', + type: 'string', + }, +]; + +const trueFalseIconProps = [ + { + default: false, + desc: 'Sets value for falsy state', + name: 'falseValue', + type: 'boolean | string', + }, + { + default: 'mdi:mdi-close', + desc: 'The false icon', + name: 'iconFalse', + type: 'string', + }, + { + default: 'danger', + desc: `${colorDesc} icon when false`, + name: 'iconFalseColor', + type: 'string', + }, + { + default: 'No', + desc: 'The title of the false icon', + name: 'iconFalseTitle', + type: 'string | undefined', + }, + { + default: 'mdi:mdi-check', + desc: 'The true icon', + name: 'iconTrue', + type: 'string', + }, + { + default: 'success', + desc: `${colorDesc} icon when true`, + name: 'iconTrueColor', + type: 'string', + }, + { + default: 'Yes', + desc: 'The title of the true icon', + name: 'iconTrueTitle', + type: 'string | undefined', + }, + { + default: true, + desc: 'Displays/Hides the icons', + name: 'icons', + type: 'boolean', + }, + { + default: true, + desc: 'Sets value for truthy state', + name: 'trueValue', + type: 'boolean | string', + }, +]; + +const truncateProps = [ + { + default: 0, + desc: 'The number of characters to truncate the displayed value', + name: 'truncateLength', + type: 'number | undefined', + }, + { + default: '...', + desc: 'The suffix to use when truncating the displayed value', + name: 'truncateSuffix', + type: 'string | undefined', + }, +]; + +const vInlineCheckboxProps = [ + ...sharedProps, + ...trueFalseIconProps, + ...[ + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: "VCheckbox['$props']['density']", + }, + { + default: 'mdi:mdi-checkbox-blank-outline', + desc: 'The icon of the field when false', + name: 'falseIcon', + type: "VCheckbox['$props']['falseIcon']", + }, + { + default: 'mdi:mdi-checkbox-outline', + desc: 'The icon of the field when true', + name: 'trueIcon', + type: "VCheckbox['$props']['trueIcon']", + }, + { + default: true, + desc: 'Displays/Hides the icons', + name: 'icons', + type: 'boolean', + }, + ] +]; + +const vInlineSelectProps = [ + ...sharedProps, + ...autofocusProp, + ...saveAndLoadingIconProps, + ...[ + { + default: 'mdi:mdi-close-circle-outline', + desc: 'The icon to use to clear the field', + name: 'clearIcon', + type: "VSelect['$props']['clearIcon']", + }, + { + default: false, + desc: 'Allows for the component to be cleared', + name: 'clearable', + type: "VSelect['$props']['clearable']", + }, + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: "VSelect['$props']['density']", + }, + { + default: true, + desc: 'Hides the selected items', + name: 'hideSelected', + type: "VSelect['$props']['hideSelected']", + }, + { + default: 'title', + desc: 'The item title', + name: 'itemTitle', + type: "VSelect['$props']['itemTitle']", + }, + { + default: 'value', + desc: 'The item value', + name: 'itemValue', + type: "VSelect['$props']['itemValue']", + }, + { + default: () => ([]), + desc: 'The select list items', + name: 'items', + type: "VSelect['$props']['items']", + }, + { + default: 'underlined', + desc: `${variantDesc} component`, + name: 'variant', + type: "VSelect['$props']['variant']", + }, + ] +]; + +const vInlineSwitchProps = [ + ...sharedProps, + ...trueFalseIconProps, + ...[ + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: "VSwitch['$props']['density']", + }, + { + default: 'mdi:mdi-checkbox-blank-outline', + desc: 'The icon of the field when false', + name: 'falseIcon', + type: "falseIcon['$props']['falseIcon']", + }, + { + default: true, + desc: 'Displays/Hides the icons', + name: 'icons', + type: 'boolean', + }, + ] +]; + +const vInlineTextareaProps = [ + ...sharedProps, + ...autofocusProp, + ...saveAndLoadingIconProps, + ...truncateProps, + ...[ + { + default: true, + desc: 'Automatically grow the textarea depending on amount of text', + name: 'autoGrow', + type: "VTextarea['$props']['autoGrow']", + }, + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: "VTextarea['$props']['density']", + }, + { + default: 1, + desc: 'Default row count', + name: 'rows', + type: "VTextarea['$props']['rows']", + }, + { + default: 'underlined', + desc: `${variantDesc} component`, + name: 'variant', + type: "VTextarea['$props']['variant']", + }, + ] +]; + +const vInlineTextFieldProps = [ + ...sharedProps, + ...autofocusProp, + ...saveAndLoadingIconProps, + ...truncateProps, + ...[ + { + default: 'compact', + desc: densityDesc, + name: 'density', + type: "VTextField['$props']['density']", + }, + { + default: 'underlined', + desc: `${variantDesc} component`, + name: 'variant', + type: "VTextField['$props']['variant']", + }, + ] +]; + +export const usePropsStore = defineStore('props', { + state: () => { + return { + autofocusProp, + propsSupported, + saveAndLoadingIconProps, + sharedProps, + trueFalseIconProps, + truncateProps, + vInlineCheckboxProps, + vInlineSelectProps, + vInlineSwitchProps, + vInlineTextFieldProps, + vInlineTextareaProps, + }; + }, +}); diff --git a/src/types/index.ts b/src/types/index.ts index 0e10a20..78a1842 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -21,10 +21,15 @@ import { export type FieldValue = string | boolean | number | object | [] | null | { [key: string]: string | unknown; }; export type TimeOpened = Date | null; +export type GlobalDensity = VCheckbox['$props']['density'] | VSelect['$props']['density'] | VSwitch['$props']['density'] | VTextField['$props']['density'] | VTextarea['$props']['density']; + +export type GlobalVariant = VSelect['$props']['variant'] | VTextField['$props']['variant'] | VTextarea['$props']['variant']; + + // -------------------------------------------------- Props // export interface SharedProps { - apiRoute?: string; + apiRoute?: string | undefined; autofocus?: boolean; cancelButtonColor?: VBtn['$props']['color']; cancelButtonSize?: VBtn['$props']['size']; @@ -49,12 +54,13 @@ export interface SharedProps { iconTrueColor?: string; iconTrueTitle?: string | undefined; icons?: boolean; - item: Record; + item?: Record; label?: string; loadingIcon?: string; loadingIconColor?: string; method?: string; - name: string; + // TODO: Change this to optional. Throw error if using apiRoute and not providing a name. // + name?: string; required?: boolean; saveButtonColor?: VBtn['$props']['color']; saveButtonSize?: VBtn['$props']['size']; @@ -62,8 +68,8 @@ export interface SharedProps { saveButtonVariant?: VBtn['$props']['variant']; saveIcon?: string; saveIconColor?: string; + tableField?: boolean; trueValue?: boolean | string; - truncateDisplayValue?: number | undefined; truncateLength?: number | undefined; truncateSuffix?: string | undefined; underlineColor?: string; @@ -108,6 +114,7 @@ export interface VInlineTextareaProps extends Omit { autoGrow?: VTextarea['$props']['autoGrow']; density?: VTextarea['$props']['density']; + rows?: VTextarea['$props']['rows']; rules?: VTextarea['$props']['rules']; variant?: VTextarea['$props']['variant']; } @@ -149,7 +156,46 @@ export interface SaveFieldButtons extends Required | string; + tableField?: SharedProps['tableField']; + }, + ): object; +} + +// ------------------------ Display Value Container // export interface UseDisplayContainerClass { + ( + options: { + density?: GlobalDensity; + field?: Ref | string; + }, + ): object; +} + +export interface UseDisplayInputControlClass { + ( + options: { + density?: GlobalDensity; + variant?: GlobalVariant; + }, + ): object; +} + +export interface UseDisplaySelectionControlClass { + ( + options: { + density?: GlobalDensity; + }, + ): object; +} + +export interface UseDisplayValueClass { ( name: string, valueColor: string, @@ -161,6 +207,17 @@ export interface UseDisplayContainerClass { ): object; } +// ------------------------ Field Container // +export interface UseFieldContainerClass { + ( + options: { + active?: Ref | boolean; + name?: Ref | string; + }, + ): object; +} + +// ------------------------ Other // export interface UseCheckForErrors { ( options: { @@ -174,7 +231,7 @@ export interface UseCheckForErrors { }; } -export interface UseFieldDisplayStyles { +export interface UseDisplayValueStyles { ( options: { color: SharedProps['color'];