diff --git a/config/sites/default/config.yaml b/config/sites/default/config.yaml index 5bada4e..c7a7746 100644 --- a/config/sites/default/config.yaml +++ b/config/sites/default/config.yaml @@ -7,6 +7,7 @@ baseVariants: dependencies: - georgringer/news - typo3/redirects + - typo3/form - cloonar-typo3/base languages: - diff --git a/package-lock.json b/package-lock.json index 0f6e87d..452e3ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,15 @@ { - "name": "lena-schilling-website", + "name": "dialog-relations-website", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "lena-schilling-website", + "name": "dialog-relations-website", "version": "1.0.0", + "dependencies": { + "yaml-loader": "^0.8.1" + }, "devDependencies": { "autoprefixer": "^10.4.21", "css-loader": "^6.7.3", @@ -944,6 +947,15 @@ "dev": true, "license": "MIT" }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -1276,6 +1288,15 @@ "dev": true, "license": "MIT" }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", @@ -1837,6 +1858,12 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "license": "MIT" + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -1896,6 +1923,18 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -1936,6 +1975,20 @@ "node": ">=6.11.5" } }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3632,7 +3685,6 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -3640,6 +3692,20 @@ "engines": { "node": ">= 14" } + }, + "node_modules/yaml-loader": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/yaml-loader/-/yaml-loader-0.8.1.tgz", + "integrity": "sha512-BCEndnUoi3BaZmePkwGGe93txRxLgMhBa/gE725v1/GHnura8QvNs7c4+4C1yyhhKoj3Dg63M7IqhA++15j6ww==", + "license": "MIT", + "dependencies": { + "javascript-stringify": "^2.0.1", + "loader-utils": "^2.0.0", + "yaml": "^2.0.0" + }, + "engines": { + "node": ">= 14" + } } } } diff --git a/package.json b/package.json index 7029d54..9ee95d0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "lena-schilling-website", + "name": "dialog-relations-website", "version": "1.0.0", "scripts": { "build:css": "NODE_ENV=production webpack --config webpack.config.js --mode production", @@ -16,5 +16,8 @@ "tailwindcss": "^3.4.17", "webpack": "^5.88.0", "webpack-cli": "^5.1.4" + }, + "dependencies": { + "yaml-loader": "^0.8.1" } } diff --git a/packages/base/Configuration/Ext/Form/TypoScript/setup.typoscript b/packages/base/Configuration/Ext/Form/TypoScript/setup.typoscript new file mode 100644 index 0000000..a9b6ca2 --- /dev/null +++ b/packages/base/Configuration/Ext/Form/TypoScript/setup.typoscript @@ -0,0 +1,15 @@ +plugin.tx_form { + settings { + yamlConfigurations { + 11 = EXT:base/Configuration/Ext/Form/Yaml/Setup.yaml + } + } +} + +module.tx_form { + settings { + yamlConfigurations { + 11 = EXT:base/Configuration/Ext/Form/Yaml/Setup.yaml + } + } +} \ No newline at end of file diff --git a/packages/base/Configuration/Ext/Form/Yaml/Setup.yaml b/packages/base/Configuration/Ext/Form/Yaml/Setup.yaml new file mode 100644 index 0000000..68c33fc --- /dev/null +++ b/packages/base/Configuration/Ext/Form/Yaml/Setup.yaml @@ -0,0 +1,200 @@ +TYPO3: + CMS: + Form: + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + templateVariant: version2 + partialRootPaths: + 20: 'EXT:base/Resources/Private/Extensions/Form/Partials/' + variants: + - + renderingOptions: + formNavigation: + btnNextClassAttribute: 'btn btn-primary' + btnPreviousClassAttribute: 'btn btn-outline btn-primary' + btnSubmitClassAttribute: 'btn btn-primary' + fieldProperties: + descriptionClassAttribute: 'form-text' + errorClassAttribute: 'peer [&_input]:input-error [&_[type=checkbox]]:checkbox-error [&_[type=file]]:file-input-error [&_[type=radio]]:radio-error [&_select]:select-error [&_textarea]:textarea-error' + errorMsgClassAttribute: 'label label-text-alt justify-start text-error peer-[.form-control]:-mt-4' + requiredMarkClassAttribute: 'required' + visuallyHiddenClassAttribute: 'sr-only' + SummaryPage: + variants: + - + renderingOptions: + listRowClassAttribute: 'grid grid-cols-2 gap-4' + + # Form elements + AdvancedPassword: + variants: + - + properties: + fieldsetClassAttribute: 'form-control form-element-advancedpassword mb-4' + containerClassAttribute: 'form-control mb-4' + elementClassAttribute: 'input input-bordered' + confirmationClassAttribute: 'input input-bordered' + labelClassAttribute: 'label label-text justify-start' + renderFieldset: 0 + Checkbox: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-checkbox mb-4' + elementClassAttribute: 'checkbox' + labelTextClassAttribute: 'label-text' + labelClassAttribute: 'label cursor-pointer justify-start gap-2' + ContentElement: + variants: + 1: + properties: + outerContainerClassAttribute: 'mb-4 [&_.container]:max-w-none [&_.frame]:py-0' + CountrySelect: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-select mb-4' + elementClassAttribute: 'select select-bordered' + labelClassAttribute: 'label label-text justify-start' + Date: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-date mb-4' + elementClassAttribute: 'input input-bordered' + labelClassAttribute: 'label label-text justify-start' + DatePicker: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-date mb-4' + elementClassAttribute: 'input input-bordered' + labelClassAttribute: 'label label-text justify-start' + SingleSelect: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-select mb-4' + elementClassAttribute: 'select select-bordered' + labelClassAttribute: 'label label-text justify-start' + StaticText: + variants: + 1: + properties: + containerClassAttribute: 'form-element-statictext mb-4 [&>p]:label-text' + Email: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-email mb-4' + elementClassAttribute: 'border border-primary block w-full p-2' + labelClassAttribute: 'label label-text font-bold justify-start block w-full mb-2' + Fieldset: + variants: + - + properties: + elementClassAttribute: 'form-element-fieldset mb-4 [&>legend]:font-bold' + FileUpload: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-fileupload mb-4' + elementClassAttribute: 'file-input file-input-bordered' + labelClassAttribute: 'label label-text justify-start' + ImageUpload: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-imageupload mb-4' + elementClassAttribute: 'file-input file-input-bordered' + labelClassAttribute: 'label label-text justify-start' + MultiCheckbox: + variants: + - + properties: + fieldsetClassAttribute: 'mb-4 [&>legend]:label [&>legend]:label-text [&>legend]:justify-start' + containerClassAttribute: 'form-control form-element-checkbox' + elementClassAttribute: 'checkbox' + labelTextClassAttribute: 'label-text' + labelClassAttribute: 'label cursor-pointer justify-start gap-2' + MultiSelect: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-multiselect mb-4' + elementClassAttribute: 'select select-bordered' + labelClassAttribute: 'label label-text justify-start' + Number: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-number mb-4' + elementClassAttribute: 'input input-bordered' + labelClassAttribute: 'label label-text justify-start' + Password: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-password mb-4' + elementClassAttribute: 'input input-bordered' + labelClassAttribute: 'label label-text justify-start' + RadioButton: + variants: + - + properties: + fieldsetClassAttribute: 'mb-4 [&>legend]:label [&>legend]:label-text [&>legend]:justify-start' + containerClassAttribute: 'form-control form-element-radio' + elementClassAttribute: 'radio' + labelTextClassAttribute: 'label-text' + labelClassAttribute: 'label cursor-pointer justify-start gap-2' + Telephone: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-phone mb-4' + elementClassAttribute: 'border border-primary block w-full p-2' + labelClassAttribute: 'label label-text font-bold justify-start block w-full mb-2' + Text: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-text mb-4' + elementClassAttribute: 'border border-primary block w-full p-2' + labelClassAttribute: 'label label-text font-bold justify-start block w-full mb-2' + Textarea: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-textarea mb-4' + elementClassAttribute: 'border border-primary block w-full p-2 h-24' + labelClassAttribute: 'label label-text font-bold justify-start block w-full mb-2' + Url: + variants: + - + properties: + containerClassAttribute: 'form-control form-element-url mb-4' + elementClassAttribute: 'border border-primary block w-full p-2' + labelClassAttribute: 'label label-text font-bold justify-start block w-full mb-2' + GridRow: + variants: + - + properties: + elementClassAttribute: 'form-element form-element-gridrow grid grid-cols-12 gap-8 md:gap-16' + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-span-{@numbersOfColumnsToUse}' + sm: + classPattern: 'sm:col-span-{@numbersOfColumnsToUse}' + md: + classPattern: 'md:col-span-{@numbersOfColumnsToUse}' + lg: + classPattern: 'lg:col-span-{@numbersOfColumnsToUse}' + xl: + classPattern: 'xl:col-span-{@numbersOfColumnsToUse}' + xxl: + classPattern: 'xxl:col-span-{@numbersOfColumnsToUse}' diff --git a/packages/base/Configuration/Sets/SitePackage/setup.typoscript b/packages/base/Configuration/Sets/SitePackage/setup.typoscript index 44b5ce0..746e688 100644 --- a/packages/base/Configuration/Sets/SitePackage/setup.typoscript +++ b/packages/base/Configuration/Sets/SitePackage/setup.typoscript @@ -1,4 +1,5 @@ @import './TypoScript/' +@import 'EXT:base/Configuration/Ext/Form/TypoScript/setup.typoscript' # Override tx_news templates plugin.tx_news { diff --git a/packages/base/Resources/Private/Extensions/Form/Partials/GridRow.html b/packages/base/Resources/Private/Extensions/Form/Partials/GridRow.html new file mode 100644 index 0000000..1274104 --- /dev/null +++ b/packages/base/Resources/Private/Extensions/Form/Partials/GridRow.html @@ -0,0 +1,11 @@ + + +
+ +
+ +
+
+
+
+ diff --git a/safelist-loader.js b/safelist-loader.js new file mode 100644 index 0000000..ead0c83 --- /dev/null +++ b/safelist-loader.js @@ -0,0 +1,62 @@ +// safelist-loader.js +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); + +/** + * Generate a Tailwind CSS safelist array from a YAML file. + * @param {string} yamlFilePath - Path to the YAML file, relative to the working directory. + * @returns {string[]} Array of unique class names. + */ +function generateSafelist(yamlFilePath) { + // Resolve the YAML file path + const absolutePath = path.resolve(process.cwd(), yamlFilePath); + const content = fs.readFileSync(absolutePath, 'utf8'); + const doc = yaml.load(content); + + const classes = new Set(); + + function walk(obj) { + if (Array.isArray(obj)) { + obj.forEach(walk); + } else if (obj && typeof obj === 'object') { + // Expand gridColumnClassAutoConfiguration placeholders + if (obj.gridColumnClassAutoConfiguration) { + const { gridSize, viewPorts } = obj.gridColumnClassAutoConfiguration; + const placeholder = /\{\@[\w]+\}/g; + if (typeof gridSize === 'number' && viewPorts) { + Object.values(viewPorts).forEach(vp => { + if (typeof vp.classPattern === 'string') { + for (let i = 1; i <= gridSize; i++) { + classes.add(vp.classPattern.replace(placeholder, i)); + } + } + }); + } + } + + // Collect any *ClassAttribute strings + Object.entries(obj).forEach(([key, val]) => { + if (/Class(Attribute)?$/.test(key) && typeof val === 'string') { + val.split(/\s+/).forEach(c => { + if (c) classes.add(c); + }); + } else { + walk(val); + } + }); + } + } + + walk(doc); + return Array.from(classes); +} + +module.exports = generateSafelist; + +// Usage in tailwind.config.js: +// const safelistLoader = require('./safelist-loader'); +// module.exports = { +// // ... other config ... +// safelist: generateSafelist('packages/base/Configuration/Ext/Form/Yaml/Setup.yaml'), +// }; diff --git a/tailwind.config.js b/tailwind.config.js index 8edbab1..b8f8c45 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,27 +1,42 @@ /** @type {import('tailwindcss').Config} */ const defaultTheme = require('tailwindcss/defaultTheme') +const safelistLoader = require('./safelist-loader'); +const safelist = safelistLoader('packages/base/Configuration/Ext/Form/Yaml/Setup.yaml'); const isProduction = process.env.NODE_ENV === 'production'; const config = { // Keep content defined always, but rely on safelist in dev content: [ + "./packages/base/Configuration/**/*.yaml", "./packages/base/Resources/Private/**/*.html", "./packages/base/Resources/Private/**/*.js", "./packages/base/ContentBlocks/ContentElements/**/*.html", "./public/typo3conf/ext/*/Resources/Private/**/*.html", ], // Disable purging in dev by safelisting everything - safelist: isProduction ? [] : [{ pattern: /.*/ }], + safelist: isProduction ? [ + ...safelist, + ] : [ + 'md:col-span-6', + { + pattern: /col-span-\d+/, + variants: ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] // Include other variants (sm, lg) if needed + }, + { pattern: /.*/ } + ], theme: { extend: { transitionProperty: { 'max-height': 'max-height' // Add max-height to transition properties }, fontFamily: { - sans: ['Inter', ...defaultTheme.fontFamily.sans], - hajime: ['"Hajime Sans"', ...defaultTheme.fontFamily.sans], + + barlow: ['"Barlow"', ...defaultTheme.fontFamily.sans], }, + // borderColor: { + // primary: 'var(--color-primary)', + // }, colors: { primary: 'var(--color-primary)', yellow: '#F5AE07',