Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
顯示
檢視
拆分
統一
即時編輯器
隱藏空白變更
摺疊未變更行
關閉換行
比對精度
智能
語法
無
變更外觀
處理
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
Start container controller diff
建立於
3 天前
差異過期
4 週後
清除
匯出
分享
解釋
45 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
163 行
全部複製
102 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
205 行
全部複製
import { raf } from '@utils/helpers';
import { raf } from '@utils/helpers';
import { isRTL } from '@utils/rtl';
import { isRTL } from '@utils/rtl';
/**
/**
* Applied to the host while the label is being repositioned. The
* Applied to the host while the label is being repositioned. The
* component stylesheets style this class, so it must stay in sync with
* component stylesheets style this class, so it must stay in sync with
* the `skip-label-transition` selector in those files. Renaming it here
* the `skip-label-transition` selector in those files. Renaming it here
* requires renaming it there too.
* requires renaming it there too.
*/
*/
export const SKIP_LABEL_TRANSITION_CLASS = 'skip-label-transition';
export const SKIP_LABEL_TRANSITION_CLASS = 'skip-label-transition';
/**
/**
* Set on the host as an inline style. The component stylesheets declare
* Set on the host as an inline style. The component stylesheets declare
* this property and read it with `var()`, so it must stay in sync with
* this property and read it with `var()`, so it must stay in sync with
* the `--internal-start-container-adjustment` references in those files.
* the `--internal-start-container-adjustment` references in those files.
* Renaming it here requires renaming it there too.
* Renaming it here requires renaming it there too.
*/
*/
export const START_CONTAINER_ADJUSTMENT_VAR = '--internal-start-container-adjustment';
export const START_CONTAINER_ADJUSTMENT_VAR = '--internal-start-container-adjustment';
/**
/**
複製
已複製
複製
已複製
* A utility to measure
and update
the start
container width adjustment
* Set on the host as an inline style. The component stylesheets declare
* for
form components
(input, textarea, select) with `fill="outline"`
.
* this property and read it with `var()`, so it must stay in sync with
* This adjustment compensates for
the
start container width
when
* the `--internal-start-end-container-width` references in those files.
* positioning
floating/stacked labels
with
in
the outline border.
* Renaming it here requires renaming it there too.
*/
export const START_END_CONTAINER_WIDTH_VAR = '--internal-start-end-container-width';
/**
* A utility to measure
the start
and end containers of
form components
*
(input, textarea, select) with `fill="outline"`
and write the results
* to
the
host. The
start container width
offsets
floating/stacked labels
* so they line up
with
the outline border.
The combined start and end
* container width lets the floating label size itself to the full width
* of the outline while still being positioned relative to the control.
*
*
* Measurement is deferred with raf() to avoid forcing layout during
* Measurement is deferred with raf() to avoid forcing layout during
* component updates, and a ResizeObserver watches for dynamic width
* component updates, and a ResizeObserver watches for dynamic width
* changes (e.g., when web fonts load or async content changes).
* changes (e.g., when web fonts load or async content changes).
*
*
* @internal
* @internal
* @param el - The host element (ion-input, ion-textarea, or ion-select).
* @param el - The host element (ion-input, ion-textarea, or ion-select).
* @param getStartContainer - A callback that returns the start container element.
* @param getStartContainer - A callback that returns the start container element.
複製
已複製
複製
已複製
* @param
shouldApplyAdjustment
- A callback that determines whether the
adjustment
should be
applied
.
* @param getEndContainer - A callback that returns the end container element.
* @param
shouldMeasure
- A callback that determines whether the
containers
should be
measured
.
*/
*/
複製
已複製
複製
已複製
export const createStart
ContainerController = (
export const createStart
End
ContainerController = (
el: HTMLElement,
el: HTMLElement,
getStartContainer: () => HTMLElement | undefined,
getStartContainer: () => HTMLElement | undefined,
複製
已複製
複製
已複製
shouldApplyAdjustment
: () => boolean
getEndContainer: () => HTMLElement | undefined,
): Start
ContainerController => {
shouldMeasure
: () => boolean
): Start
End
ContainerController => {
let resizeObserver: ResizeObserver | undefined;
let resizeObserver: ResizeObserver | undefined;
複製
已複製
複製
已複製
let
observedContainer
: HTMLElement | undefined;
let
observedStartContainer: HTMLElement | undefined;
let observedEndContainer
: HTMLElement | undefined;
let measurementRaf: number | undefined;
let measurementRaf: number | undefined;
let transitionRaf: number | undefined;
let transitionRaf: number | undefined;
let appliedAdjustment: string | undefined;
let appliedAdjustment: string | undefined;
複製
已複製
複製
已複製
let appliedStartEndWidth: string | undefined;
const calculateAdjustment = (): string => {
const startSlot = getStartContainer();
if (!startSlot || !shouldApplyAdjustment()) {
return '';
}
複製
已複製
複製
已複製
/*
/*
* Round to one decimal place so fractional widths produce a stable
* Round to one decimal place so fractional widths produce a stable
* label offset
when
the start
container is added, removed, or resized.
* label offset
and width
when
a
container is added, removed, or resized.
*/
*/
const startContainerWidth =
startSlot
.getBoundingClientRect().width
;
const roundWidth = (width: number) => Math.round(width * 10) / 10;
const
roundedWidth = Math.round(startContainerWidth * 10) / 10;
const measureContainers = (): { adjustment: string; startEndWidth: string } => {
const startContainer = getStartContainer();
if (!startContainer || !shouldMeasure()) {
return { adjustment: '', startEndWidth: '' };
}
const startContainerWidth =
roundWidth(startContainer
.getBoundingClientRect().width
)
;
const
endContainerWidth = roundWidth(getEndContainer()?.getBoundingClientRect().width ?? 0);
const sign = isRTL(el) ? '' : '-';
const sign = isRTL(el) ? '' : '-';
複製
已複製
複製
已複製
return
roundedWidth
? `${sign}${
roundedWidth
}px` : '0px'
;
return
{
adjustment: startContainerWidth
? `${sign}${
startContainerWidth
}px` : '0px'
,
startEndWidth: `${roundWidth(startContainerWidth + endContainerWidth)}px`,
}
;
};
};
複製
已複製
複製
已複製
const
scheduleAdjustmentUpdate
= () => {
const
scheduleMeasurement
= () => {
// Return if there is already a measurement queued to avoid a flicker
// Return if there is already a measurement queued to avoid a flicker
if (measurementRaf !== undefined) {
if (measurementRaf !== undefined) {
return;
return;
}
}
/*
/*
* Defer the measurement until the next animation frame so layout
* Defer the measurement until the next animation frame so layout
* is measured after the current update has been applied.
* is measured after the current update has been applied.
*/
*/
measurementRaf = raf(() => {
measurementRaf = raf(() => {
measurementRaf = undefined;
measurementRaf = undefined;
複製
已複製
複製
已複製
const
adjustment
= calculateAdjustment();
const
{
adjustment
, startEndWidth } = measureContainers();
/*
* The width only changes how much of the label fits, so it can
* animate. The transition is not suppressed here because the end
* container can change size while the label is floating, such as
* when async content loads, and that should not cut the float short.
*/
if (startEndWidth !== appliedStartEndWidth) {
el.style.setProperty(START_END_CONTAINER_WIDTH_VAR, startEndWidth);
appliedStartEndWidth = startEndWidth;
}
// Only suppress the label transition when the label has to move
// Only suppress the label transition when the label has to move
if (adjustment !== appliedAdjustment) {
if (adjustment !== appliedAdjustment) {
// Discard a removal queued by an earlier change
// Discard a removal queued by an earlier change
if (transitionRaf !== undefined) {
if (transitionRaf !== undefined) {
cancelAnimationFrame(transitionRaf);
cancelAnimationFrame(transitionRaf);
}
}
el.classList.add(SKIP_LABEL_TRANSITION_CLASS);
el.classList.add(SKIP_LABEL_TRANSITION_CLASS);
el.style.setProperty(START_CONTAINER_ADJUSTMENT_VAR, adjustment);
el.style.setProperty(START_CONTAINER_ADJUSTMENT_VAR, adjustment);
appliedAdjustment = adjustment;
appliedAdjustment = adjustment;
// Re-enable the transition once the new offset has been painted
// Re-enable the transition once the new offset has been painted
transitionRaf = raf(() => {
transitionRaf = raf(() => {
transitionRaf = undefined;
transitionRaf = undefined;
el.classList.remove(SKIP_LABEL_TRANSITION_CLASS);
el.classList.remove(SKIP_LABEL_TRANSITION_CLASS);
});
});
}
}
setupResizeObserver();
setupResizeObserver();
});
});
};
};
const disconnectResizeObserver = () => {
const disconnectResizeObserver = () => {
if (resizeObserver) {
if (resizeObserver) {
resizeObserver.disconnect();
resizeObserver.disconnect();
resizeObserver = undefined;
resizeObserver = undefined;
複製
已複製
複製
已複製
observedContainer
= undefined;
observedStartContainer = undefined;
observedEndContainer
= undefined;
}
}
};
};
const setupResizeObserver = () => {
const setupResizeObserver = () => {
複製
已複製
複製
已複製
const
startSlot
= getStartContainer();
const
startContainer
= getStartContainer();
const endContainer = getEndContainer();
複製
已複製
複製
已複製
// Stop watching once the
adjustment
no longer appl
ies
// Stop watching once the
measurements
no longer appl
y
if (!
startSlot
|| !
shouldApplyAdjustment
()) {
if (!
startContainer
|| !
shouldMeasure
()) {
disconnectResizeObserver();
disconnectResizeObserver();
return;
return;
}
}
複製
已複製
複製
已複製
// Return when prerendering or already watching th
is
container
// Return when prerendering or already watching th
ese
container
s
if (
typeof ResizeObserver !== 'function' ||
(resizeObserver && observed
Container ===
startSlot)
) {
if (
typeof ResizeObserver !== 'function' ||
(resizeObserver && observed
Start
Container ===
startContainer && observedEndContainer === endContainer)
) {
return;
return;
}
}
disconnectResizeObserver();
disconnectResizeObserver();
resizeObserver = new ResizeObserver(() => {
resizeObserver = new ResizeObserver(() => {
複製
已複製
複製
已複製
scheduleAdjustmentUpdate
();
scheduleMeasurement
();
});
});
複製
已複製
複製
已複製
observed
Container =
startSlot
;
observed
Start
Container =
startContainer
;
resizeObserver.observe(
startSlot);
resizeObserver.observe(
startContainer);
if (endContainer) {
observedEndContainer = endContainer;
resizeObserver.observe(endContainer);
}
};
};
複製
已複製
複製
已複製
const calculate
Start
ContainerWidth
= () => {
const calculate
ContainerWidth
s
= () => {
scheduleAdjustmentUpdate
();
scheduleMeasurement
();
};
};
const destroy = () => {
const destroy = () => {
disconnectResizeObserver();
disconnectResizeObserver();
if (measurementRaf !== undefined) {
if (measurementRaf !== undefined) {
cancelAnimationFrame(measurementRaf);
cancelAnimationFrame(measurementRaf);
measurementRaf = undefined;
measurementRaf = undefined;
}
}
// Tearing down mid-toggle would leave the transition disabled
// Tearing down mid-toggle would leave the transition disabled
if (transitionRaf !== undefined) {
if (transitionRaf !== undefined) {
cancelAnimationFrame(transitionRaf);
cancelAnimationFrame(transitionRaf);
transitionRaf = undefined;
transitionRaf = undefined;
el.classList.remove(SKIP_LABEL_TRANSITION_CLASS);
el.classList.remove(SKIP_LABEL_TRANSITION_CLASS);
}
}
// Re-apply from scratch if the element is connected again
// Re-apply from scratch if the element is connected again
appliedAdjustment = undefined;
appliedAdjustment = undefined;
複製
已複製
複製
已複製
appliedStartEndWidth = undefined;
};
};
return {
return {
複製
已複製
複製
已複製
calculate
Start
ContainerWidth
,
calculate
ContainerWidth
s
,
destroy,
destroy,
};
};
};
};
複製
已複製
複製
已複製
export type Start
ContainerController = {
export type Start
End
ContainerController = {
calculate
Start
ContainerWidth
: () => void;
calculate
ContainerWidth
s
: () => void;
destroy: () => void;
destroy: () => void;
};
};
已保存差異
原始文本
開啟檔案
import { raf } from '@utils/helpers'; import { isRTL } from '@utils/rtl'; /** * Applied to the host while the label is being repositioned. The * component stylesheets style this class, so it must stay in sync with * the `skip-label-transition` selector in those files. Renaming it here * requires renaming it there too. */ export const SKIP_LABEL_TRANSITION_CLASS = 'skip-label-transition'; /** * Set on the host as an inline style. The component stylesheets declare * this property and read it with `var()`, so it must stay in sync with * the `--internal-start-container-adjustment` references in those files. * Renaming it here requires renaming it there too. */ export const START_CONTAINER_ADJUSTMENT_VAR = '--internal-start-container-adjustment'; /** * A utility to measure and update the start container width adjustment * for form components (input, textarea, select) with `fill="outline"`. * This adjustment compensates for the start container width when * positioning floating/stacked labels within the outline border. * * Measurement is deferred with raf() to avoid forcing layout during * component updates, and a ResizeObserver watches for dynamic width * changes (e.g., when web fonts load or async content changes). * * @internal * @param el - The host element (ion-input, ion-textarea, or ion-select). * @param getStartContainer - A callback that returns the start container element. * @param shouldApplyAdjustment - A callback that determines whether the adjustment should be applied. */ export const createStartContainerController = ( el: HTMLElement, getStartContainer: () => HTMLElement | undefined, shouldApplyAdjustment: () => boolean ): StartContainerController => { let resizeObserver: ResizeObserver | undefined; let observedContainer: HTMLElement | undefined; let measurementRaf: number | undefined; let transitionRaf: number | undefined; let appliedAdjustment: string | undefined; const calculateAdjustment = (): string => { const startSlot = getStartContainer(); if (!startSlot || !shouldApplyAdjustment()) { return ''; } /* * Round to one decimal place so fractional widths produce a stable * label offset when the start container is added, removed, or resized. */ const startContainerWidth = startSlot.getBoundingClientRect().width; const roundedWidth = Math.round(startContainerWidth * 10) / 10; const sign = isRTL(el) ? '' : '-'; return roundedWidth ? `${sign}${roundedWidth}px` : '0px'; }; const scheduleAdjustmentUpdate = () => { // Return if there is already a measurement queued to avoid a flicker if (measurementRaf !== undefined) { return; } /* * Defer the measurement until the next animation frame so layout * is measured after the current update has been applied. */ measurementRaf = raf(() => { measurementRaf = undefined; const adjustment = calculateAdjustment(); // Only suppress the label transition when the label has to move if (adjustment !== appliedAdjustment) { // Discard a removal queued by an earlier change if (transitionRaf !== undefined) { cancelAnimationFrame(transitionRaf); } el.classList.add(SKIP_LABEL_TRANSITION_CLASS); el.style.setProperty(START_CONTAINER_ADJUSTMENT_VAR, adjustment); appliedAdjustment = adjustment; // Re-enable the transition once the new offset has been painted transitionRaf = raf(() => { transitionRaf = undefined; el.classList.remove(SKIP_LABEL_TRANSITION_CLASS); }); } setupResizeObserver(); }); }; const disconnectResizeObserver = () => { if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = undefined; observedContainer = undefined; } }; const setupResizeObserver = () => { const startSlot = getStartContainer(); // Stop watching once the adjustment no longer applies if (!startSlot || !shouldApplyAdjustment()) { disconnectResizeObserver(); return; } // Return when prerendering or already watching this container if (typeof ResizeObserver !== 'function' || (resizeObserver && observedContainer === startSlot)) { return; } disconnectResizeObserver(); resizeObserver = new ResizeObserver(() => { scheduleAdjustmentUpdate(); }); observedContainer = startSlot; resizeObserver.observe(startSlot); }; const calculateStartContainerWidth = () => { scheduleAdjustmentUpdate(); }; const destroy = () => { disconnectResizeObserver(); if (measurementRaf !== undefined) { cancelAnimationFrame(measurementRaf); measurementRaf = undefined; } // Tearing down mid-toggle would leave the transition disabled if (transitionRaf !== undefined) { cancelAnimationFrame(transitionRaf); transitionRaf = undefined; el.classList.remove(SKIP_LABEL_TRANSITION_CLASS); } // Re-apply from scratch if the element is connected again appliedAdjustment = undefined; }; return { calculateStartContainerWidth, destroy, }; }; export type StartContainerController = { calculateStartContainerWidth: () => void; destroy: () => void; };
更改後文本
開啟檔案
import { raf } from '@utils/helpers'; import { isRTL } from '@utils/rtl'; /** * Applied to the host while the label is being repositioned. The * component stylesheets style this class, so it must stay in sync with * the `skip-label-transition` selector in those files. Renaming it here * requires renaming it there too. */ export const SKIP_LABEL_TRANSITION_CLASS = 'skip-label-transition'; /** * Set on the host as an inline style. The component stylesheets declare * this property and read it with `var()`, so it must stay in sync with * the `--internal-start-container-adjustment` references in those files. * Renaming it here requires renaming it there too. */ export const START_CONTAINER_ADJUSTMENT_VAR = '--internal-start-container-adjustment'; /** * Set on the host as an inline style. The component stylesheets declare * this property and read it with `var()`, so it must stay in sync with * the `--internal-start-end-container-width` references in those files. * Renaming it here requires renaming it there too. */ export const START_END_CONTAINER_WIDTH_VAR = '--internal-start-end-container-width'; /** * A utility to measure the start and end containers of form components * (input, textarea, select) with `fill="outline"` and write the results * to the host. The start container width offsets floating/stacked labels * so they line up with the outline border. The combined start and end * container width lets the floating label size itself to the full width * of the outline while still being positioned relative to the control. * * Measurement is deferred with raf() to avoid forcing layout during * component updates, and a ResizeObserver watches for dynamic width * changes (e.g., when web fonts load or async content changes). * * @internal * @param el - The host element (ion-input, ion-textarea, or ion-select). * @param getStartContainer - A callback that returns the start container element. * @param getEndContainer - A callback that returns the end container element. * @param shouldMeasure - A callback that determines whether the containers should be measured. */ export const createStartEndContainerController = ( el: HTMLElement, getStartContainer: () => HTMLElement | undefined, getEndContainer: () => HTMLElement | undefined, shouldMeasure: () => boolean ): StartEndContainerController => { let resizeObserver: ResizeObserver | undefined; let observedStartContainer: HTMLElement | undefined; let observedEndContainer: HTMLElement | undefined; let measurementRaf: number | undefined; let transitionRaf: number | undefined; let appliedAdjustment: string | undefined; let appliedStartEndWidth: string | undefined; /* * Round to one decimal place so fractional widths produce a stable * label offset and width when a container is added, removed, or resized. */ const roundWidth = (width: number) => Math.round(width * 10) / 10; const measureContainers = (): { adjustment: string; startEndWidth: string } => { const startContainer = getStartContainer(); if (!startContainer || !shouldMeasure()) { return { adjustment: '', startEndWidth: '' }; } const startContainerWidth = roundWidth(startContainer.getBoundingClientRect().width); const endContainerWidth = roundWidth(getEndContainer()?.getBoundingClientRect().width ?? 0); const sign = isRTL(el) ? '' : '-'; return { adjustment: startContainerWidth ? `${sign}${startContainerWidth}px` : '0px', startEndWidth: `${roundWidth(startContainerWidth + endContainerWidth)}px`, }; }; const scheduleMeasurement = () => { // Return if there is already a measurement queued to avoid a flicker if (measurementRaf !== undefined) { return; } /* * Defer the measurement until the next animation frame so layout * is measured after the current update has been applied. */ measurementRaf = raf(() => { measurementRaf = undefined; const { adjustment, startEndWidth } = measureContainers(); /* * The width only changes how much of the label fits, so it can * animate. The transition is not suppressed here because the end * container can change size while the label is floating, such as * when async content loads, and that should not cut the float short. */ if (startEndWidth !== appliedStartEndWidth) { el.style.setProperty(START_END_CONTAINER_WIDTH_VAR, startEndWidth); appliedStartEndWidth = startEndWidth; } // Only suppress the label transition when the label has to move if (adjustment !== appliedAdjustment) { // Discard a removal queued by an earlier change if (transitionRaf !== undefined) { cancelAnimationFrame(transitionRaf); } el.classList.add(SKIP_LABEL_TRANSITION_CLASS); el.style.setProperty(START_CONTAINER_ADJUSTMENT_VAR, adjustment); appliedAdjustment = adjustment; // Re-enable the transition once the new offset has been painted transitionRaf = raf(() => { transitionRaf = undefined; el.classList.remove(SKIP_LABEL_TRANSITION_CLASS); }); } setupResizeObserver(); }); }; const disconnectResizeObserver = () => { if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = undefined; observedStartContainer = undefined; observedEndContainer = undefined; } }; const setupResizeObserver = () => { const startContainer = getStartContainer(); const endContainer = getEndContainer(); // Stop watching once the measurements no longer apply if (!startContainer || !shouldMeasure()) { disconnectResizeObserver(); return; } // Return when prerendering or already watching these containers if ( typeof ResizeObserver !== 'function' || (resizeObserver && observedStartContainer === startContainer && observedEndContainer === endContainer) ) { return; } disconnectResizeObserver(); resizeObserver = new ResizeObserver(() => { scheduleMeasurement(); }); observedStartContainer = startContainer; resizeObserver.observe(startContainer); if (endContainer) { observedEndContainer = endContainer; resizeObserver.observe(endContainer); } }; const calculateContainerWidths = () => { scheduleMeasurement(); }; const destroy = () => { disconnectResizeObserver(); if (measurementRaf !== undefined) { cancelAnimationFrame(measurementRaf); measurementRaf = undefined; } // Tearing down mid-toggle would leave the transition disabled if (transitionRaf !== undefined) { cancelAnimationFrame(transitionRaf); transitionRaf = undefined; el.classList.remove(SKIP_LABEL_TRANSITION_CLASS); } // Re-apply from scratch if the element is connected again appliedAdjustment = undefined; appliedStartEndWidth = undefined; }; return { calculateContainerWidths, destroy, }; }; export type StartEndContainerController = { calculateContainerWidths: () => void; destroy: () => void; };
尋找差異