diff --git a/readme.txt b/readme.txt index b20e8474f..3b858e614 100644 --- a/readme.txt +++ b/readme.txt @@ -111,6 +111,8 @@ e.g. [ Editor Design Bug Fix ] [ Grid Column (Pro) ] Fixed an issue where the 'is-vertical' layout of grid column items was not displayed vertically. +[ Add function ][ Core Table ] Add table cell vertical setting. + = 1.94.2 = [ Bug fix / Specification Change ][ Visual Embed ] Strengthened validation for XSS protection and restricted the range of allowed URLs. diff --git a/src/extensions/core/table/style.js b/src/extensions/core/table/style.js index 9afbfb794..b76f71cf5 100644 --- a/src/extensions/core/table/style.js +++ b/src/extensions/core/table/style.js @@ -56,6 +56,14 @@ export const addAttribute = (settings) => { type: 'boolean', default: true, }, + cellVertical: { + type: 'boolean', + default: false, + }, + cellVerticalBreakpoint: { + type: 'string', + default: 'table-cell-vertical-mobile', + }, }; } return settings; @@ -74,25 +82,48 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { scrollIconRight, iconOutputLeft, iconOutputRight, + cellVertical, + cellVerticalBreakpoint, } = attributes; const blockProps = useBlockProps({ - className: scrollable ? 'is-style-vk-table-scrollable' : '', + className: + `${scrollable ? 'is-style-vk-table-scrollable' : ''} ${cellVertical ? 'is-style-vk-table-cell-vertical' : ''}`.trim(), + ...(scrollable && { 'data-scroll-breakpoint': scrollBreakpoint }), + ...(cellVertical && { + 'data-cell-vertical-breakpoint': cellVerticalBreakpoint, + }), }); // アイコンスタイルを定義 - let iconStyle = { + const iconStyle = { width: '24px', height: '24px', }; - if (scrollable) { - iconStyle = { - ...iconStyle, - color: '#fff', - background: '#1e1e1e', - }; - } + // scrollable に関連するアイコンスタイル + const scrollableIconStyle = { + color: scrollable ? '#fff' : 'initial', // scrollable が ON のときは白、OFF のときはデフォルト + background: scrollable ? '#1e1e1e' : 'transparent', // scrollable が ON のときは背景色、OFF のときは透明 + }; + + // cellVertical に関連するアイコンスタイル + const cellVerticalIconStyle = { + color: cellVertical ? '#fff' : 'initial', // cellVertical が ON のときは白、OFF のときはデフォルト + background: cellVertical ? '#1e1e1e' : 'transparent', // cellVertical が ON のときは背景色、OFF のときは透明 + }; + + // scrollable 用アイコンスタイルを独立して適用 + const scrollableIconStyleFinal = { + ...iconStyle, + ...scrollableIconStyle, + }; + + // cellVertical 用アイコンスタイルを独立して適用 + const cellVerticalIconStyleFinal = { + ...iconStyle, + ...cellVerticalIconStyle, + }; // スクロール可能トグル変更のハンドル const handleToggleChange = (checked) => { @@ -111,9 +142,26 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { setAttributes({ scrollBreakpoint: value }); }; + // cellVerticalトグル変更のハンドル + const handleCellVerticalToggleChange = (checked) => { + setAttributes({ cellVertical: checked }); + + if (!checked) { + // OFF の場合、関連するクラスや属性をリセット + setAttributes({ + cellVerticalBreakpoint: 'table-cell-vertical-mobile', + }); + } + }; + + // cellVerticalブレークポイント選択変更のハンドル + const handleCellVerticalSelectChange = (value) => { + setAttributes({ cellVerticalBreakpoint: value }); + }; + // コンポーネントのマウントまたは更新後に属性を更新 useEffect(() => { - // 初期ロード時にクラスや属性を確認して scrollable を ON にする + // 初期ロード時にクラスや属性を確認して scrollable を ON にする∂ const checkTableScrollAttributes = () => { const tables = document.querySelectorAll('.wp-block-table'); tables.forEach((table) => { @@ -133,13 +181,13 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { checkTableScrollAttributes(); }, []); // 初期レンダリング時のみ実行 - // scrollable の状態が確定したら処理を実行 + // scrollable、cellVertical の状態が確定したら処理を実行 useEffect(() => { - const updateTableScrollAttributes = () => { - const tables = document.querySelectorAll( - '.wp-block-table.is-style-vk-table-scrollable' - ); + const updateTableAttributes = () => { + // .wp-block-table を持つすべてのテーブル要素を取得 + const tables = document.querySelectorAll('.wp-block-table'); tables.forEach((table) => { + // scrollable 状態に応じてクラスと属性を更新 if (!scrollable) { table.classList.remove('is-style-vk-table-scrollable'); table.removeAttribute('data-scroll-breakpoint'); @@ -147,6 +195,7 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { const breakpoint = table.getAttribute('data-scroll-breakpoint') || 'table-scrollable-mobile'; + table.classList.add('is-style-vk-table-scrollable'); table.setAttribute( 'data-scroll-breakpoint', breakpoint @@ -167,11 +216,28 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { 'data-icon-output-right', iconOutputRight ? 'true' : 'false' ); + + // cellVertical 状態に応じたクラスと属性を更新 + if (!cellVertical) { + // cellVertical が OFF の場合 + table.classList.remove( + 'is-style-vk-table-cell-vertical' + ); + table.removeAttribute('data-cell-vertical-breakpoint'); + } else { + // cellVertical が ON の場合 + table.classList.add('is-style-vk-table-cell-vertical'); + table.setAttribute( + 'data-cell-vertical-breakpoint', + cellVerticalBreakpoint + ); + } }); }; + // 状態が undefined でない場合のみ実行 if (typeof scrollable !== 'undefined') { - updateTableScrollAttributes(); + updateTableAttributes(); } }, [ scrollable, @@ -181,6 +247,8 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { scrollIconRight, iconOutputLeft, iconOutputRight, + cellVertical, + cellVerticalBreakpoint, ]); if (isValidBlockType(name) && props.isSelected) { @@ -227,7 +295,12 @@ export const addBlockControl = createHigherOrderComponent((BlockEdit) => { 'Table Horizontal Scroll', 'vk-blocks-pro' )} - icon={} + icon={ + + } initialOpen={false} > { )} + + } + initialOpen={false} + > + + {cellVertical && ( + <> + + + )} + ); @@ -297,12 +423,19 @@ const addExtraProps = (saveElementProps, blockType, attributes) => { `${saveElementProps.className || ''} is-style-vk-table-scrollable`.trim(); saveElementProps['data-scroll-breakpoint'] = attributes.scrollBreakpoint; + } + + // cellVerticalがtrueの場合にcellVerticalBreakpointを設定 + if (attributes.cellVertical) { + saveElementProps.className += ` is-style-vk-table-cell-vertical`; + saveElementProps['data-cell-vertical-breakpoint'] = + attributes.cellVerticalBreakpoint; } else { - // 'scrollable' が false の場合、クラスと属性を削除 + // cellVerticalがfalseの場合、不要なクラスや属性を削除 saveElementProps.className = saveElementProps.className - .replace('is-style-vk-table-scrollable', '') + .replace('is-style-vk-table-cell-vertical', '') .trim(); - delete saveElementProps['data-scroll-breakpoint']; + delete saveElementProps['data-cell-vertical-breakpoint']; } // 'showScrollMessage' が true の場合のみ 'data-output-scroll-hint' を追加 @@ -331,6 +464,7 @@ const addExtraProps = (saveElementProps, blockType, attributes) => { delete saveElementProps['data-output-scroll-hint']; delete saveElementProps['data-icon-output-left']; delete saveElementProps['data-icon-output-right']; + delete saveElementProps['data-cell-vertical-breakpoint']; } return saveElementProps; @@ -340,3 +474,35 @@ addFilter( 'vk-blocks/table-style', addExtraProps ); + +const removeVkTableMobileBlockFromEditor = createHigherOrderComponent( + (BlockListBlock) => { + return (props) => { + const { attributes, setAttributes } = props; + + // `cellVertical` が `true` の場合のみ `.vk-table--mobile-block` を削除 + if ( + attributes?.cellVertical && + attributes?.className?.includes('vk-table--mobile-block') + ) { + const updatedClassName = attributes.className + .replace(/\bvk-table--mobile-block\b/g, '') + .trim(); + + // `setAttributes` を使用して `className` を更新 + if (updatedClassName !== attributes.className) { + setAttributes({ className: updatedClassName }); + } + } + + return ; + }; + }, + 'withRemoveVkTableMobileBlock' +); + +addFilter( + 'editor.BlockListBlock', + 'vk-blocks/remove-vk-table-mobile-block', + removeVkTableMobileBlockFromEditor +); diff --git a/src/extensions/core/table/style.scss b/src/extensions/core/table/style.scss index 04e6b40b9..8d609245d 100644 --- a/src/extensions/core/table/style.scss +++ b/src/extensions/core/table/style.scss @@ -36,6 +36,42 @@ } } +// 縦積み +@mixin cell-vertical-table { + + table { + + :is(th, td) { + width: 100%; + display: block; + border-top-color: transparent; + box-sizing: border-box; + + /* 最後のセルには border-bottom: none を適用 */ + &:last-of-type:not(:last-child) { + border-bottom: none + } + } + } + + /* 最初の行を除外するためのスタイル */ + &:not(.is-style-stripes) tr:first-of-type :is(th, td):first-of-type { + border-top: 1px solid; + } + + &.is-style-vk-table { + &-border-top-bottom, + &-border, + &-border-stripes { + // theme.json のあるファイルでテーブルの線の色指定がない場合のみ適用 + table:not(.has-border-color) { + tr:first-of-type :is(th, td):first-of-type { + border-top: 1px solid var(--vk-color-border-hr); + } + } + } + } +} /* フロントエンド /*-------------------------------------------*/ @@ -105,6 +141,25 @@ @include scrollable-table; } } + + &.is-style-vk-table-cell-vertical { + + &[data-cell-vertical-breakpoint="table-cell-vertical-mobile"] { + @media (max-width: 575.98px) { + @include cell-vertical-table; + } + } + + &[data-cell-vertical-breakpoint="table-cell-vertical-tablet"] { + @media (max-width: 991.98px) { + @include cell-vertical-table; + } + } + + &[data-cell-vertical-breakpoint="table-cell-vertical-pc"] { + @include cell-vertical-table; + } + } } /* 編集画面 @@ -116,8 +171,51 @@ border-color: var(--vk-color-border-hr); } } + + &.is-style-vk-table-scrollable { - @include scrollable-table-editor; + + &[data-scroll-breakpoint="table-scrollable-mobile"] { + @media (max-width: 575.98px) { + @include scrollable-table-editor; + } + } + + &[data-scroll-breakpoint="table-scrollable-tablet"] { + @media (max-width: 991.98px) { + @include scrollable-table-editor; + } + } + + &[data-scroll-breakpoint="table-scrollable-pc"] { + @include scrollable-table-editor; + } + } + + &.is-style-vk-table-cell-vertical { + + /* 最初の行を除外するためのスタイル */ + &:not(.is-style-stripes) table:not(.has-border-color) { + tr:first-of-type :is(th, td):first-of-type { + border-top: 1px solid var(--vk-color-border-hr); + } + } + + &[data-cell-vertical-breakpoint="table-cell-vertical-mobile"] { + @media (max-width: 575.98px) { + @include cell-vertical-table; + } + } + + &[data-cell-vertical-breakpoint="table-cell-vertical-tablet"] { + @media (max-width: 991.98px) { + @include cell-vertical-table; + } + } + + &[data-cell-vertical-breakpoint="table-cell-vertical-pc"] { + @include cell-vertical-table; + } } } }